Source Code
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
There are no matching entriesUpdate your filters to view other transactions | |||||||||
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LockProxy
Compiler Version
v0.6.12+commit.27d51765
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2020-11-09
*/
// File: contracts/libs/common/ZeroCopySource.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
/**
* @dev Wrappers over decoding and deserialization operation from bytes into bassic types in Solidity for PolyNetwork cross chain utility.
*
* Decode into basic types in Solidity from bytes easily. It's designed to be used
* for PolyNetwork cross chain application, and the decoding rules on Ethereum chain
* and the encoding rule on other chains should be consistent, and . Here we
* follow the underlying deserialization rule with implementation found here:
* https://github.com/polynetwork/poly/blob/master/common/zero_copy_source.go
*
* Using this library instead of the unchecked serialization method can help reduce
* the risk of serious bugs and handfule, so it's recommended to use it.
*
* Please note that risk can be minimized, yet not eliminated.
*/
library ZeroCopySource {
/* @notice Read next byte as boolean type starting at offset from buff
* @param buff Source bytes array
* @param offset The position from where we read the boolean value
* @return The the read boolean value and new offset
*/
function NextBool(bytes memory buff, uint256 offset) internal pure returns(bool, uint256) {
require(offset + 1 <= buff.length && offset < offset + 1, "Offset exceeds limit");
// byte === bytes1
byte v;
assembly{
v := mload(add(add(buff, 0x20), offset))
}
bool value;
if (v == 0x01) {
value = true;
} else if (v == 0x00) {
value = false;
} else {
revert("NextBool value error");
}
return (value, offset + 1);
}
/* @notice Read next byte starting at offset from buff
* @param buff Source bytes array
* @param offset The position from where we read the byte value
* @return The read byte value and new offset
*/
function NextByte(bytes memory buff, uint256 offset) internal pure returns (byte, uint256) {
require(offset + 1 <= buff.length && offset < offset + 1, "NextByte, Offset exceeds maximum");
byte v;
assembly{
v := mload(add(add(buff, 0x20), offset))
}
return (v, offset + 1);
}
/* @notice Read next byte as uint8 starting at offset from buff
* @param buff Source bytes array
* @param offset The position from where we read the byte value
* @return The read uint8 value and new offset
*/
function NextUint8(bytes memory buff, uint256 offset) internal pure returns (uint8, uint256) {
require(offset + 1 <= buff.length && offset < offset + 1, "NextUint8, Offset exceeds maximum");
uint8 v;
assembly{
let tmpbytes := mload(0x40)
let bvalue := mload(add(add(buff, 0x20), offset))
mstore8(tmpbytes, byte(0, bvalue))
mstore(0x40, add(tmpbytes, 0x01))
v := mload(sub(tmpbytes, 0x1f))
}
return (v, offset + 1);
}
/* @notice Read next two bytes as uint16 type starting from offset
* @param buff Source bytes array
* @param offset The position from where we read the uint16 value
* @return The read uint16 value and updated offset
*/
function NextUint16(bytes memory buff, uint256 offset) internal pure returns (uint16, uint256) {
require(offset + 2 <= buff.length && offset < offset + 2, "NextUint16, offset exceeds maximum");
uint16 v;
assembly {
let tmpbytes := mload(0x40)
let bvalue := mload(add(add(buff, 0x20), offset))
mstore8(tmpbytes, byte(0x01, bvalue))
mstore8(add(tmpbytes, 0x01), byte(0, bvalue))
mstore(0x40, add(tmpbytes, 0x02))
v := mload(sub(tmpbytes, 0x1e))
}
return (v, offset + 2);
}
/* @notice Read next four bytes as uint32 type starting from offset
* @param buff Source bytes array
* @param offset The position from where we read the uint32 value
* @return The read uint32 value and updated offset
*/
function NextUint32(bytes memory buff, uint256 offset) internal pure returns (uint32, uint256) {
require(offset + 4 <= buff.length && offset < offset + 4, "NextUint32, offset exceeds maximum");
uint32 v;
assembly {
let tmpbytes := mload(0x40)
let byteLen := 0x04
for {
let tindex := 0x00
let bindex := sub(byteLen, 0x01)
let bvalue := mload(add(add(buff, 0x20), offset))
} lt(tindex, byteLen) {
tindex := add(tindex, 0x01)
bindex := sub(bindex, 0x01)
}{
mstore8(add(tmpbytes, tindex), byte(bindex, bvalue))
}
mstore(0x40, add(tmpbytes, byteLen))
v := mload(sub(tmpbytes, sub(0x20, byteLen)))
}
return (v, offset + 4);
}
/* @notice Read next eight bytes as uint64 type starting from offset
* @param buff Source bytes array
* @param offset The position from where we read the uint64 value
* @return The read uint64 value and updated offset
*/
function NextUint64(bytes memory buff, uint256 offset) internal pure returns (uint64, uint256) {
require(offset + 8 <= buff.length && offset < offset + 8, "NextUint64, offset exceeds maximum");
uint64 v;
assembly {
let tmpbytes := mload(0x40)
let byteLen := 0x08
for {
let tindex := 0x00
let bindex := sub(byteLen, 0x01)
let bvalue := mload(add(add(buff, 0x20), offset))
} lt(tindex, byteLen) {
tindex := add(tindex, 0x01)
bindex := sub(bindex, 0x01)
}{
mstore8(add(tmpbytes, tindex), byte(bindex, bvalue))
}
mstore(0x40, add(tmpbytes, byteLen))
v := mload(sub(tmpbytes, sub(0x20, byteLen)))
}
return (v, offset + 8);
}
/* @notice Read next 32 bytes as uint256 type starting from offset,
there are limits considering the numerical limits in multi-chain
* @param buff Source bytes array
* @param offset The position from where we read the uint256 value
* @return The read uint256 value and updated offset
*/
function NextUint255(bytes memory buff, uint256 offset) internal pure returns (uint256, uint256) {
require(offset + 32 <= buff.length && offset < offset + 32, "NextUint255, offset exceeds maximum");
uint256 v;
assembly {
let tmpbytes := mload(0x40)
let byteLen := 0x20
for {
let tindex := 0x00
let bindex := sub(byteLen, 0x01)
let bvalue := mload(add(add(buff, 0x20), offset))
} lt(tindex, byteLen) {
tindex := add(tindex, 0x01)
bindex := sub(bindex, 0x01)
}{
mstore8(add(tmpbytes, tindex), byte(bindex, bvalue))
}
mstore(0x40, add(tmpbytes, byteLen))
v := mload(tmpbytes)
}
require(v <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds the range");
return (v, offset + 32);
}
/* @notice Read next variable bytes starting from offset,
the decoding rule coming from multi-chain
* @param buff Source bytes array
* @param offset The position from where we read the bytes value
* @return The read variable bytes array value and updated offset
*/
function NextVarBytes(bytes memory buff, uint256 offset) internal pure returns(bytes memory, uint256) {
uint len;
(len, offset) = NextVarUint(buff, offset);
require(offset + len <= buff.length && offset < offset + len, "NextVarBytes, offset exceeds maximum");
bytes memory tempBytes;
assembly{
switch iszero(len)
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(len, 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, len)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(add(add(buff, lengthmod), mul(0x20, iszero(lengthmod))), offset)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, len)
//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)
mstore(0x40, add(tempBytes, 0x20))
}
}
return (tempBytes, offset + len);
}
/* @notice Read next 32 bytes starting from offset,
* @param buff Source bytes array
* @param offset The position from where we read the bytes value
* @return The read bytes32 value and updated offset
*/
function NextHash(bytes memory buff, uint256 offset) internal pure returns (bytes32 , uint256) {
require(offset + 32 <= buff.length && offset < offset + 32, "NextHash, offset exceeds maximum");
bytes32 v;
assembly {
v := mload(add(buff, add(offset, 0x20)))
}
return (v, offset + 32);
}
/* @notice Read next 20 bytes starting from offset,
* @param buff Source bytes array
* @param offset The position from where we read the bytes value
* @return The read bytes20 value and updated offset
*/
function NextBytes20(bytes memory buff, uint256 offset) internal pure returns (bytes20 , uint256) {
require(offset + 20 <= buff.length && offset < offset + 20, "NextBytes20, offset exceeds maximum");
bytes20 v;
assembly {
v := mload(add(buff, add(offset, 0x20)))
}
return (v, offset + 20);
}
function NextVarUint(bytes memory buff, uint256 offset) internal pure returns(uint, uint256) {
byte v;
(v, offset) = NextByte(buff, offset);
uint value;
if (v == 0xFD) {
// return NextUint16(buff, offset);
(value, offset) = NextUint16(buff, offset);
require(value >= 0xFD && value <= 0xFFFF, "NextUint16, value outside range");
return (value, offset);
} else if (v == 0xFE) {
// return NextUint32(buff, offset);
(value, offset) = NextUint32(buff, offset);
require(value > 0xFFFF && value <= 0xFFFFFFFF, "NextVarUint, value outside range");
return (value, offset);
} else if (v == 0xFF) {
// return NextUint64(buff, offset);
(value, offset) = NextUint64(buff, offset);
require(value > 0xFFFFFFFF, "NextVarUint, value outside range");
return (value, offset);
} else{
// return (uint8(v), offset);
value = uint8(v);
require(value < 0xFD, "NextVarUint, value outside range");
return (value, offset);
}
}
}
// File: contracts/libs/common/ZeroCopySink.sol
pragma solidity 0.6.12;
/**
* @dev Wrappers over encoding and serialization operation into bytes from bassic types in Solidity for PolyNetwork cross chain utility.
*
* Encode basic types in Solidity into bytes easily. It's designed to be used
* for PolyNetwork cross chain application, and the encoding rules on Ethereum chain
* and the decoding rules on other chains should be consistent. Here we
* follow the underlying serialization rule with implementation found here:
* https://github.com/polynetwork/poly/blob/master/common/zero_copy_sink.go
*
* Using this library instead of the unchecked serialization method can help reduce
* the risk of serious bugs and handfule, so it's recommended to use it.
*
* Please note that risk can be minimized, yet not eliminated.
*/
library ZeroCopySink {
/* @notice Convert boolean value into bytes
* @param b The boolean value
* @return Converted bytes array
*/
function WriteBool(bool b) internal pure returns (bytes memory) {
bytes memory buff;
assembly{
buff := mload(0x40)
mstore(buff, 1)
switch iszero(b)
case 1 {
mstore(add(buff, 0x20), shl(248, 0x00))
// mstore8(add(buff, 0x20), 0x00)
}
default {
mstore(add(buff, 0x20), shl(248, 0x01))
// mstore8(add(buff, 0x20), 0x01)
}
mstore(0x40, add(buff, 0x21))
}
return buff;
}
/* @notice Convert byte value into bytes
* @param b The byte value
* @return Converted bytes array
*/
function WriteByte(byte b) internal pure returns (bytes memory) {
return WriteUint8(uint8(b));
}
/* @notice Convert uint8 value into bytes
* @param v The uint8 value
* @return Converted bytes array
*/
function WriteUint8(uint8 v) internal pure returns (bytes memory) {
bytes memory buff;
assembly{
buff := mload(0x40)
mstore(buff, 1)
mstore(add(buff, 0x20), shl(248, v))
// mstore(add(buff, 0x20), byte(0x1f, v))
mstore(0x40, add(buff, 0x21))
}
return buff;
}
/* @notice Convert uint16 value into bytes
* @param v The uint16 value
* @return Converted bytes array
*/
function WriteUint16(uint16 v) internal pure returns (bytes memory) {
bytes memory buff;
assembly{
buff := mload(0x40)
let byteLen := 0x02
mstore(buff, byteLen)
for {
let mindex := 0x00
let vindex := 0x1f
} lt(mindex, byteLen) {
mindex := add(mindex, 0x01)
vindex := sub(vindex, 0x01)
}{
mstore8(add(add(buff, 0x20), mindex), byte(vindex, v))
}
mstore(0x40, add(buff, 0x22))
}
return buff;
}
/* @notice Convert uint32 value into bytes
* @param v The uint32 value
* @return Converted bytes array
*/
function WriteUint32(uint32 v) internal pure returns(bytes memory) {
bytes memory buff;
assembly{
buff := mload(0x40)
let byteLen := 0x04
mstore(buff, byteLen)
for {
let mindex := 0x00
let vindex := 0x1f
} lt(mindex, byteLen) {
mindex := add(mindex, 0x01)
vindex := sub(vindex, 0x01)
}{
mstore8(add(add(buff, 0x20), mindex), byte(vindex, v))
}
mstore(0x40, add(buff, 0x24))
}
return buff;
}
/* @notice Convert uint64 value into bytes
* @param v The uint64 value
* @return Converted bytes array
*/
function WriteUint64(uint64 v) internal pure returns(bytes memory) {
bytes memory buff;
assembly{
buff := mload(0x40)
let byteLen := 0x08
mstore(buff, byteLen)
for {
let mindex := 0x00
let vindex := 0x1f
} lt(mindex, byteLen) {
mindex := add(mindex, 0x01)
vindex := sub(vindex, 0x01)
}{
mstore8(add(add(buff, 0x20), mindex), byte(vindex, v))
}
mstore(0x40, add(buff, 0x28))
}
return buff;
}
/* @notice Convert limited uint256 value into bytes
* @param v The uint256 value
* @return Converted bytes array
*/
function WriteUint255(uint256 v) internal pure returns (bytes memory) {
require(v <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds uint255 range");
bytes memory buff;
assembly{
buff := mload(0x40)
let byteLen := 0x20
mstore(buff, byteLen)
for {
let mindex := 0x00
let vindex := 0x1f
} lt(mindex, byteLen) {
mindex := add(mindex, 0x01)
vindex := sub(vindex, 0x01)
}{
mstore8(add(add(buff, 0x20), mindex), byte(vindex, v))
}
mstore(0x40, add(buff, 0x40))
}
return buff;
}
/* @notice Encode bytes format data into bytes
* @param data The bytes array data
* @return Encoded bytes array
*/
function WriteVarBytes(bytes memory data) internal pure returns (bytes memory) {
uint64 l = uint64(data.length);
return abi.encodePacked(WriteVarUint(l), data);
}
function WriteVarUint(uint64 v) internal pure returns (bytes memory) {
if (v < 0xFD){
return WriteUint8(uint8(v));
} else if (v <= 0xFFFF) {
return abi.encodePacked(WriteByte(0xFD), WriteUint16(uint16(v)));
} else if (v <= 0xFFFFFFFF) {
return abi.encodePacked(WriteByte(0xFE), WriteUint32(uint32(v)));
} else {
return abi.encodePacked(WriteByte(0xFF), WriteUint64(uint64(v)));
}
}
}
// File: contracts/libs/utils/ReentrancyGuard.sol
pragma solidity 0.6.12;
/**
* @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].
*/
contract ReentrancyGuard {
bool private _notEntered;
constructor () internal {
// Storing an initial 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 percetange 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.
_notEntered = true;
}
/**
* @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 make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_notEntered, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_notEntered = false;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_notEntered = true;
}
}
// File: contracts/libs/utils/Utils.sol
pragma solidity 0.6.12;
library Utils {
/* @notice Convert the bytes array to bytes32 type, the bytes array length must be 32
* @param _bs Source bytes array
* @return bytes32
*/
function bytesToBytes32(bytes memory _bs) internal pure returns (bytes32 value) {
require(_bs.length == 32, "bytes length is not 32.");
assembly {
// load 32 bytes from memory starting from position _bs + 0x20 since the first 0x20 bytes stores _bs length
value := mload(add(_bs, 0x20))
}
}
/* @notice Convert bytes to uint256
* @param _b Source bytes should have length of 32
* @return uint256
*/
function bytesToUint256(bytes memory _bs) internal pure returns (uint256 value) {
require(_bs.length == 32, "bytes length is not 32.");
assembly {
// load 32 bytes from memory starting from position _bs + 32
value := mload(add(_bs, 0x20))
}
require(value <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds the range");
}
/* @notice Convert uint256 to bytes
* @param _b uint256 that needs to be converted
* @return bytes
*/
function uint256ToBytes(uint256 _value) internal pure returns (bytes memory bs) {
require(_value <= 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, "Value exceeds the range");
assembly {
// Get a location of some free memory and store it in result as
// Solidity does for memory variables.
bs := mload(0x40)
// Put 0x20 at the first word, the length of bytes for uint256 value
mstore(bs, 0x20)
//In the next word, put value in bytes format to the next 32 bytes
mstore(add(bs, 0x20), _value)
// Update the free-memory pointer by padding our last write location to 32 bytes
mstore(0x40, add(bs, 0x40))
}
}
/* @notice Convert bytes to address
* @param _bs Source bytes: bytes length must be 20
* @return Converted address from source bytes
*/
function bytesToAddress(bytes memory _bs) internal pure returns (address addr)
{
require(_bs.length == 20, "bytes length does not match address");
assembly {
// for _bs, first word store _bs.length, second word store _bs.value
// load 32 bytes from mem[_bs+20], convert it into Uint160, meaning we take last 20 bytes as addr (address).
addr := mload(add(_bs, 0x14))
}
}
/* @notice Convert address to bytes
* @param _addr Address need to be converted
* @return Converted bytes from address
*/
function addressToBytes(address _addr) internal pure returns (bytes memory bs){
assembly {
// Get a location of some free memory and store it in result as
// Solidity does for memory variables.
bs := mload(0x40)
// Put 20 (address byte length) at the first word, the length of bytes for uint256 value
mstore(bs, 0x14)
// logical shift left _a by 12 bytes, change _a from right-aligned to left-aligned
mstore(add(bs, 0x20), shl(96, _addr))
// Update the free-memory pointer by padding our last write location to 32 bytes
mstore(0x40, add(bs, 0x40))
}
}
/* @notice Do hash leaf as the multi-chain does
* @param _data Data in bytes format
* @return Hashed value in bytes32 format
*/
function hashLeaf(bytes memory _data) internal pure returns (bytes32 result) {
result = sha256(abi.encodePacked(byte(0x0), _data));
}
/* @notice Do hash children as the multi-chain does
* @param _l Left node
* @param _r Right node
* @return Hashed value in bytes32 format
*/
function hashChildren(bytes32 _l, bytes32 _r) internal pure returns (bytes32 result) {
result = sha256(abi.encodePacked(bytes1(0x01), _l, _r));
}
/* @notice Compare if two bytes are equal, which are in storage and memory, seperately
Refer from https://github.com/summa-tx/bitcoin-spv/blob/master/solidity/contracts/BytesLib.sol#L368
* @param _preBytes The bytes stored in storage
* @param _postBytes The bytes stored in memory
* @return Bool type indicating if they are equal
*/
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)
// 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)
// if lengths don't match the arrays are not equal
switch eq(slength, mlength)
case 1 {
// fslot can contain both the length and contents of the array
// if slength < 32 bytes so let's prepare for that
// v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
// slength != 0
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(uint(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;
}
/* @notice Slice the _bytes from _start index till the result has length of _length
Refer from https://github.com/summa-tx/bitcoin-spv/blob/master/solidity/contracts/BytesLib.sol#L246
* @param _bytes The original bytes needs to be sliced
* @param _start The index of _bytes for the start of sliced bytes
* @param _length The index of _bytes for the end of sliced bytes
* @return The sliced bytes
*/
function slice(
bytes memory _bytes,
uint _start,
uint _length
)
internal
pure
returns (bytes memory)
{
require(_bytes.length >= (_start + _length));
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.
// lengthmod <= _length % 32
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)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
/* @notice Check if the elements number of _signers within _keepers array is no less than _m
* @param _keepers The array consists of serveral address
* @param _signers Some specific addresses to be looked into
* @param _m The number requirement paramter
* @return True means containment, false meansdo do not contain.
*/
function containMAddresses(address[] memory _keepers, address[] memory _signers, uint _m) internal pure returns (bool){
uint m = 0;
for(uint i = 0; i < _signers.length; i++){
for (uint j = 0; j < _keepers.length; j++) {
if (_signers[i] == _keepers[j]) {
m++;
delete _keepers[j];
}
}
}
return m >= _m;
}
/* @notice TODO
* @param key
* @return
*/
function compressMCPubKey(bytes memory key) internal pure returns (bytes memory newkey) {
require(key.length >= 67, "key lenggh is too short");
newkey = slice(key, 0, 35);
if (uint8(key[66]) % 2 == 0){
newkey[2] = byte(0x02);
} else {
newkey[2] = byte(0x03);
}
return newkey;
}
/**
* @dev Returns true if `account` is a contract.
* Refer from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol#L18
*
* This test is non-exhaustive, and there may be false-negatives: during the
* execution of a contract's constructor, its address will be reported as
* not containing 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.
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != 0x0 && codehash != accountHash);
}
}
// File: contracts/libs/math/SafeMath.sol
pragma solidity 0.6.12;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
// File: contracts/Wallet.sol
pragma solidity 0.6.12;
interface ERC20 {
function approve(address spender, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
}
/// @title The Wallet contract for Switcheo TradeHub
/// @author Switcheo Network
/// @notice This contract faciliates deposits for Switcheo TradeHub.
/// @dev This contract is used together with the LockProxy contract to allow users
/// to deposit funds without requiring them to have ETH
contract Wallet {
bool public isInitialized;
address public creator;
address public owner;
bytes public swthAddress;
function initialize(address _owner, bytes calldata _swthAddress) external {
require(isInitialized == false, "Contract already initialized");
isInitialized = true;
creator = msg.sender;
owner = _owner;
swthAddress = _swthAddress;
}
/// @dev Allow this contract to receive Ethereum
receive() external payable {}
/// @dev Allow this contract to receive ERC223 tokens
// An empty implementation is required so that the ERC223 token will not
// throw an error on transfer
function tokenFallback(address, uint, bytes calldata) external {}
/// @dev send ETH from this contract to its creator
function sendETHToCreator(uint256 _amount) external {
require(msg.sender == creator, "Sender must be creator");
// we use `call` here following the recommendation from
// https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/
(bool success, ) = creator.call{value: _amount}("");
require(success, "Transfer failed");
}
/// @dev send tokens from this contract to its creator
function sendERC20ToCreator(address _assetId, uint256 _amount) external {
require(msg.sender == creator, "Sender must be creator");
ERC20 token = ERC20(_assetId);
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.transfer.selector,
creator,
_amount
)
);
}
/**
* @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(ERC20 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.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(_isContract(address(token)), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
/**
* @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
* ====
*/
function _isContract(address account) private view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
}
// File: contracts/LockProxy.sol
pragma solidity 0.6.12;
interface CCM {
function crossChain(uint64 _toChainId, bytes calldata _toContract, bytes calldata _method, bytes calldata _txData) external returns (bool);
}
interface CCMProxy {
function getEthCrossChainManager() external view returns (address);
}
/// @title The LockProxy contract for Switcheo TradeHub
/// @author Switcheo Network
/// @notice This contract faciliates deposits and withdrawals to Switcheo TradeHub.
/// @dev The contract also allows for additional features in the future through "extension" contracts.
contract LockProxy is ReentrancyGuard {
using SafeMath for uint256;
// used for cross-chain addExtension and removeExtension methods
struct ExtensionTxArgs {
bytes extensionAddress;
}
// used for cross-chain registerAsset method
struct RegisterAssetTxArgs {
bytes assetHash;
bytes nativeAssetHash;
}
// used for cross-chain lock and unlock methods
struct TransferTxArgs {
bytes fromAssetHash;
bytes toAssetHash;
bytes toAddress;
uint256 amount;
uint256 feeAmount;
bytes feeAddress;
bytes fromAddress;
uint256 nonce;
}
// used to create a unique salt for wallet creation
bytes public constant SALT_PREFIX = "switcheo-eth-wallet-factory-v1";
address public constant ETH_ASSET_HASH = address(0);
CCMProxy public ccmProxy;
uint64 public counterpartChainId;
uint256 public currentNonce = 0;
// a mapping of assetHashes to the hash of
// (associated proxy address on Switcheo TradeHub, associated asset hash on Switcheo TradeHub)
mapping(address => bytes32) public registry;
// a record of signed messages to prevent replay attacks
mapping(bytes32 => bool) public seenMessages;
// a mapping of extension contracts
mapping(address => bool) public extensions;
// a record of created wallets
mapping(address => bool) public wallets;
event LockEvent(
address fromAssetHash,
address fromAddress,
uint64 toChainId,
bytes toAssetHash,
bytes toAddress,
bytes txArgs
);
event UnlockEvent(
address toAssetHash,
address toAddress,
uint256 amount,
bytes txArgs
);
constructor(address _ccmProxyAddress, uint64 _counterpartChainId) public {
require(_counterpartChainId > 0, "counterpartChainId cannot be zero");
require(_ccmProxyAddress != address(0), "ccmProxyAddress cannot be empty");
counterpartChainId = _counterpartChainId;
ccmProxy = CCMProxy(_ccmProxyAddress);
}
modifier onlyManagerContract() {
require(
msg.sender == ccmProxy.getEthCrossChainManager(),
"msg.sender is not CCM"
);
_;
}
/// @dev Allow this contract to receive Ethereum
receive() external payable {}
/// @dev Allow this contract to receive ERC223 tokens
/// An empty implementation is required so that the ERC223 token will not
/// throw an error on transfer, this is specific to ERC223 tokens which
/// require this implementation, e.g. DGTX
function tokenFallback(address, uint, bytes calldata) external {}
/// @dev Calculate the wallet address for the given owner and Switcheo TradeHub address
/// @param _ownerAddress the Ethereum address which the user has control over, i.e. can sign msgs with
/// @param _swthAddress the hex value of the user's Switcheo TradeHub address
/// @param _bytecodeHash the hash of the wallet contract's bytecode
/// @return the wallet address
function getWalletAddress(
address _ownerAddress,
bytes calldata _swthAddress,
bytes32 _bytecodeHash
)
external
view
returns (address)
{
bytes32 salt = _getSalt(
_ownerAddress,
_swthAddress
);
bytes32 data = keccak256(
abi.encodePacked(bytes1(0xff), address(this), salt, _bytecodeHash)
);
return address(bytes20(data << 96));
}
/// @dev Create the wallet for the given owner and Switcheo TradeHub address
/// @param _ownerAddress the Ethereum address which the user has control over, i.e. can sign msgs with
/// @param _swthAddress the hex value of the user's Switcheo TradeHub address
/// @return true if success
function createWallet(
address _ownerAddress,
bytes calldata _swthAddress
)
external
nonReentrant
returns (bool)
{
require(_ownerAddress != address(0), "Empty ownerAddress");
require(_swthAddress.length != 0, "Empty swthAddress");
bytes32 salt = _getSalt(
_ownerAddress,
_swthAddress
);
Wallet wallet = new Wallet{salt: salt}();
wallet.initialize(_ownerAddress, _swthAddress);
wallets[address(wallet)] = true;
return true;
}
/// @dev Add a contract as an extension
/// @param _argsBz the serialized ExtensionTxArgs
/// @param _fromChainId the originating chainId
/// @return true if success
function addExtension(
bytes calldata _argsBz,
bytes calldata /* _fromContractAddr */,
uint64 _fromChainId
)
external
onlyManagerContract
nonReentrant
returns (bool)
{
require(_fromChainId == counterpartChainId, "Invalid chain ID");
ExtensionTxArgs memory args = _deserializeExtensionTxArgs(_argsBz);
address extensionAddress = Utils.bytesToAddress(args.extensionAddress);
extensions[extensionAddress] = true;
return true;
}
/// @dev Remove a contract from the extensions mapping
/// @param _argsBz the serialized ExtensionTxArgs
/// @param _fromChainId the originating chainId
/// @return true if success
function removeExtension(
bytes calldata _argsBz,
bytes calldata /* _fromContractAddr */,
uint64 _fromChainId
)
external
onlyManagerContract
nonReentrant
returns (bool)
{
require(_fromChainId == counterpartChainId, "Invalid chain ID");
ExtensionTxArgs memory args = _deserializeExtensionTxArgs(_argsBz);
address extensionAddress = Utils.bytesToAddress(args.extensionAddress);
extensions[extensionAddress] = false;
return true;
}
/// @dev Marks an asset as registered by mapping the asset's address to
/// the specified _fromContractAddr and assetHash on Switcheo TradeHub
/// @param _argsBz the serialized RegisterAssetTxArgs
/// @param _fromContractAddr the associated contract address on Switcheo TradeHub
/// @param _fromChainId the originating chainId
/// @return true if success
function registerAsset(
bytes calldata _argsBz,
bytes calldata _fromContractAddr,
uint64 _fromChainId
)
external
onlyManagerContract
nonReentrant
returns (bool)
{
require(_fromChainId == counterpartChainId, "Invalid chain ID");
RegisterAssetTxArgs memory args = _deserializeRegisterAssetTxArgs(_argsBz);
_markAssetAsRegistered(
Utils.bytesToAddress(args.nativeAssetHash),
_fromContractAddr,
args.assetHash
);
return true;
}
/// @dev Performs a deposit from a Wallet contract
/// @param _walletAddress address of the wallet contract, the wallet contract
/// does not receive ETH in this call, but _walletAddress still needs to be payable
/// since the wallet contract can receive ETH, there would be compile errors otherwise
/// @param _assetHash the asset to deposit
/// @param _targetProxyHash the associated proxy hash on Switcheo TradeHub
/// @param _toAssetHash the associated asset hash on Switcheo TradeHub
/// @param _feeAddress the hex version of the Switcheo TradeHub address to send the fee to
/// @param _values[0]: amount, the number of tokens to deposit
/// @param _values[1]: feeAmount, the number of tokens to be used as fees
/// @param _values[2]: nonce, to prevent replay attacks
/// @param _values[3]: callAmount, some tokens may burn an amount before transfer
/// so we allow a callAmount to support these tokens
/// @param _v: the v value of the wallet owner's signature
/// @param _rs: the r, s values of the wallet owner's signature
function lockFromWallet(
address payable _walletAddress,
address _assetHash,
bytes calldata _targetProxyHash,
bytes calldata _toAssetHash,
bytes calldata _feeAddress,
uint256[] calldata _values,
uint8 _v,
bytes32[] calldata _rs
)
external
nonReentrant
returns (bool)
{
require(wallets[_walletAddress], "Invalid wallet address");
Wallet wallet = Wallet(_walletAddress);
_validateLockFromWallet(
wallet.owner(),
_assetHash,
_targetProxyHash,
_toAssetHash,
_feeAddress,
_values,
_v,
_rs
);
// it is very important that this function validates the success of a transfer correctly
// since, once this line is passed, the deposit is assumed to be successful
// which will eventually result in the specified amount of tokens being minted for the
// wallet.swthAddress on Switcheo TradeHub
_transferInFromWallet(_walletAddress, _assetHash, _values[0], _values[3]);
_lock(
_assetHash,
_targetProxyHash,
_toAssetHash,
wallet.swthAddress(),
_values[0],
_values[1],
_feeAddress
);
return true;
}
/// @dev Performs a deposit
/// @param _assetHash the asset to deposit
/// @param _targetProxyHash the associated proxy hash on Switcheo TradeHub
/// @param _toAddress the hex version of the Switcheo TradeHub address to deposit to
/// @param _toAssetHash the associated asset hash on Switcheo TradeHub
/// @param _feeAddress the hex version of the Switcheo TradeHub address to send the fee to
/// @param _values[0]: amount, the number of tokens to deposit
/// @param _values[1]: feeAmount, the number of tokens to be used as fees
/// @param _values[2]: callAmount, some tokens may burn an amount before transfer
/// so we allow a callAmount to support these tokens
function lock(
address _assetHash,
bytes calldata _targetProxyHash,
bytes calldata _toAddress,
bytes calldata _toAssetHash,
bytes calldata _feeAddress,
uint256[] calldata _values
)
external
payable
nonReentrant
returns (bool)
{
// it is very important that this function validates the success of a transfer correctly
// since, once this line is passed, the deposit is assumed to be successful
// which will eventually result in the specified amount of tokens being minted for the
// _toAddress on Switcheo TradeHub
_transferIn(_assetHash, _values[0], _values[2]);
_lock(
_assetHash,
_targetProxyHash,
_toAssetHash,
_toAddress,
_values[0],
_values[1],
_feeAddress
);
return true;
}
/// @dev Performs a withdrawal that was initiated on Switcheo TradeHub
/// @param _argsBz the serialized TransferTxArgs
/// @param _fromContractAddr the associated contract address on Switcheo TradeHub
/// @param _fromChainId the originating chainId
/// @return true if success
function unlock(
bytes calldata _argsBz,
bytes calldata _fromContractAddr,
uint64 _fromChainId
)
external
onlyManagerContract
nonReentrant
returns (bool)
{
require(_fromChainId == counterpartChainId, "Invalid chain ID");
TransferTxArgs memory args = _deserializeTransferTxArgs(_argsBz);
require(args.fromAssetHash.length > 0, "Invalid fromAssetHash");
require(args.toAssetHash.length == 20, "Invalid toAssetHash");
address toAssetHash = Utils.bytesToAddress(args.toAssetHash);
address toAddress = Utils.bytesToAddress(args.toAddress);
_validateAssetRegistration(toAssetHash, _fromContractAddr, args.fromAssetHash);
_transferOut(toAddress, toAssetHash, args.amount);
emit UnlockEvent(toAssetHash, toAddress, args.amount, _argsBz);
return true;
}
/// @dev Performs a transfer of funds, this is only callable by approved extension contracts
/// the `nonReentrant` guard is intentionally not added to this function, to allow for more flexibility.
/// The calling contract should be secure and have its own `nonReentrant` guard as needed.
/// @param _receivingAddress the address to transfer to
/// @param _assetHash the asset to transfer
/// @param _amount the amount to transfer
/// @return true if success
function extensionTransfer(
address _receivingAddress,
address _assetHash,
uint256 _amount
)
external
returns (bool)
{
require(
extensions[msg.sender] == true,
"Invalid extension"
);
if (_assetHash == ETH_ASSET_HASH) {
// we use `call` here since the _receivingAddress could be a contract
// see https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/
// for more info
(bool success, ) = _receivingAddress.call{value: _amount}("");
require(success, "Transfer failed");
return true;
}
ERC20 token = ERC20(_assetHash);
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.approve.selector,
_receivingAddress,
_amount
)
);
return true;
}
/// @dev Marks an asset as registered by associating it to a specified Switcheo TradeHub proxy and asset hash
/// @param _assetHash the address of the asset to mark
/// @param _proxyAddress the associated proxy address on Switcheo TradeHub
/// @param _toAssetHash the associated asset hash on Switcheo TradeHub
function _markAssetAsRegistered(
address _assetHash,
bytes memory _proxyAddress,
bytes memory _toAssetHash
)
private
{
require(_proxyAddress.length == 20, "Invalid proxyAddress");
require(
registry[_assetHash] == bytes32(0),
"Asset already registered"
);
bytes32 value = keccak256(abi.encodePacked(
_proxyAddress,
_toAssetHash
));
registry[_assetHash] = value;
}
/// @dev Validates that an asset's registration matches the given params
/// @param _assetHash the address of the asset to check
/// @param _proxyAddress the expected proxy address on Switcheo TradeHub
/// @param _toAssetHash the expected asset hash on Switcheo TradeHub
function _validateAssetRegistration(
address _assetHash,
bytes memory _proxyAddress,
bytes memory _toAssetHash
)
private
view
{
require(_proxyAddress.length == 20, "Invalid proxyAddress");
bytes32 value = keccak256(abi.encodePacked(
_proxyAddress,
_toAssetHash
));
require(registry[_assetHash] == value, "Asset not registered");
}
/// @dev validates the asset registration and calls the CCM contract
function _lock(
address _fromAssetHash,
bytes memory _targetProxyHash,
bytes memory _toAssetHash,
bytes memory _toAddress,
uint256 _amount,
uint256 _feeAmount,
bytes memory _feeAddress
)
private
{
require(_targetProxyHash.length == 20, "Invalid targetProxyHash");
require(_toAssetHash.length > 0, "Empty toAssetHash");
require(_toAddress.length > 0, "Empty toAddress");
require(_amount > 0, "Amount must be more than zero");
require(_feeAmount < _amount, "Fee amount cannot be greater than amount");
_validateAssetRegistration(_fromAssetHash, _targetProxyHash, _toAssetHash);
TransferTxArgs memory txArgs = TransferTxArgs({
fromAssetHash: Utils.addressToBytes(_fromAssetHash),
toAssetHash: _toAssetHash,
toAddress: _toAddress,
amount: _amount,
feeAmount: _feeAmount,
feeAddress: _feeAddress,
fromAddress: abi.encodePacked(msg.sender),
nonce: _getNextNonce()
});
bytes memory txData = _serializeTransferTxArgs(txArgs);
CCM ccm = _getCcm();
require(
ccm.crossChain(counterpartChainId, _targetProxyHash, "unlock", txData),
"EthCrossChainManager crossChain executed error!"
);
emit LockEvent(_fromAssetHash, msg.sender, counterpartChainId, _toAssetHash, _toAddress, txData);
}
/// @dev validate the signature for lockFromWallet
function _validateLockFromWallet(
address _walletOwner,
address _assetHash,
bytes memory _targetProxyHash,
bytes memory _toAssetHash,
bytes memory _feeAddress,
uint256[] memory _values,
uint8 _v,
bytes32[] memory _rs
)
private
{
bytes32 message = keccak256(abi.encodePacked(
"sendTokens",
_assetHash,
_targetProxyHash,
_toAssetHash,
_feeAddress,
_values[0],
_values[1],
_values[2]
));
require(seenMessages[message] == false, "Message already seen");
seenMessages[message] = true;
_validateSignature(message, _walletOwner, _v, _rs[0], _rs[1]);
}
/// @dev transfers funds from a Wallet contract into this contract
/// the difference between this contract's before and after balance must equal _amount
/// this is assumed to be sufficient in ensuring that the expected amount
/// of funds were transferred in
function _transferInFromWallet(
address payable _walletAddress,
address _assetHash,
uint256 _amount,
uint256 _callAmount
)
private
{
Wallet wallet = Wallet(_walletAddress);
if (_assetHash == ETH_ASSET_HASH) {
uint256 before = address(this).balance;
wallet.sendETHToCreator(_callAmount);
uint256 transferred = address(this).balance.sub(before);
require(transferred == _amount, "ETH transferred does not match the expected amount");
return;
}
ERC20 token = ERC20(_assetHash);
uint256 before = token.balanceOf(address(this));
wallet.sendERC20ToCreator(_assetHash, _callAmount);
uint256 transferred = token.balanceOf(address(this)).sub(before);
require(transferred == _amount, "Tokens transferred does not match the expected amount");
}
/// @dev transfers funds from an address into this contract
/// for ETH transfers, we only check that msg.value == _amount, and _callAmount is ignored
/// for token transfers, the difference between this contract's before and after balance must equal _amount
/// these checks are assumed to be sufficient in ensuring that the expected amount
/// of funds were transferred in
function _transferIn(
address _assetHash,
uint256 _amount,
uint256 _callAmount
)
private
{
if (_assetHash == ETH_ASSET_HASH) {
require(msg.value == _amount, "ETH transferred does not match the expected amount");
return;
}
ERC20 token = ERC20(_assetHash);
uint256 before = token.balanceOf(address(this));
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.transferFrom.selector,
msg.sender,
address(this),
_callAmount
)
);
uint256 transferred = token.balanceOf(address(this)).sub(before);
require(transferred == _amount, "Tokens transferred does not match the expected amount");
}
/// @dev transfers funds from this contract to the _toAddress
function _transferOut(
address _toAddress,
address _assetHash,
uint256 _amount
)
private
{
if (_assetHash == ETH_ASSET_HASH) {
// we use `call` here since the _receivingAddress could be a contract
// see https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/
// for more info
(bool success, ) = _toAddress.call{value: _amount}("");
require(success, "Transfer failed");
return;
}
ERC20 token = ERC20(_assetHash);
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.transfer.selector,
_toAddress,
_amount
)
);
}
/// @dev validates a signature against the specified user address
function _validateSignature(
bytes32 _message,
address _user,
uint8 _v,
bytes32 _r,
bytes32 _s
)
private
pure
{
bytes32 prefixedMessage = keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
_message
));
require(
_user == ecrecover(prefixedMessage, _v, _r, _s),
"Invalid signature"
);
}
function _serializeTransferTxArgs(TransferTxArgs memory args) private pure returns (bytes memory) {
bytes memory buff;
buff = abi.encodePacked(
ZeroCopySink.WriteVarBytes(args.fromAssetHash),
ZeroCopySink.WriteVarBytes(args.toAssetHash),
ZeroCopySink.WriteVarBytes(args.toAddress),
ZeroCopySink.WriteUint255(args.amount),
ZeroCopySink.WriteUint255(args.feeAmount),
ZeroCopySink.WriteVarBytes(args.feeAddress),
ZeroCopySink.WriteVarBytes(args.fromAddress),
ZeroCopySink.WriteUint255(args.nonce)
);
return buff;
}
function _deserializeTransferTxArgs(bytes memory valueBz) private pure returns (TransferTxArgs memory) {
TransferTxArgs memory args;
uint256 off = 0;
(args.fromAssetHash, off) = ZeroCopySource.NextVarBytes(valueBz, off);
(args.toAssetHash, off) = ZeroCopySource.NextVarBytes(valueBz, off);
(args.toAddress, off) = ZeroCopySource.NextVarBytes(valueBz, off);
(args.amount, off) = ZeroCopySource.NextUint255(valueBz, off);
return args;
}
function _deserializeRegisterAssetTxArgs(bytes memory valueBz) private pure returns (RegisterAssetTxArgs memory) {
RegisterAssetTxArgs memory args;
uint256 off = 0;
(args.assetHash, off) = ZeroCopySource.NextVarBytes(valueBz, off);
(args.nativeAssetHash, off) = ZeroCopySource.NextVarBytes(valueBz, off);
return args;
}
function _deserializeExtensionTxArgs(bytes memory valueBz) private pure returns (ExtensionTxArgs memory) {
ExtensionTxArgs memory args;
uint256 off = 0;
(args.extensionAddress, off) = ZeroCopySource.NextVarBytes(valueBz, off);
return args;
}
function _getCcm() private view returns (CCM) {
CCM ccm = CCM(ccmProxy.getEthCrossChainManager());
return ccm;
}
function _getNextNonce() private returns (uint256) {
currentNonce = currentNonce.add(1);
return currentNonce;
}
function _getSalt(
address _ownerAddress,
bytes memory _swthAddress
)
private
pure
returns (bytes32)
{
return keccak256(abi.encodePacked(
SALT_PREFIX,
_ownerAddress,
_swthAddress
));
}
/**
* @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(ERC20 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.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(_isContract(address(token)), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
/**
* @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
* ====
*/
function _isContract(address account) private view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_ccmProxyAddress","type":"address"},{"internalType":"uint64","name":"_counterpartChainId","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"fromAssetHash","type":"address"},{"indexed":false,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":false,"internalType":"uint64","name":"toChainId","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"toAssetHash","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"toAddress","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"txArgs","type":"bytes"}],"name":"LockEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"toAssetHash","type":"address"},{"indexed":false,"internalType":"address","name":"toAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"txArgs","type":"bytes"}],"name":"UnlockEvent","type":"event"},{"inputs":[],"name":"ETH_ASSET_HASH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALT_PREFIX","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_argsBz","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"_fromChainId","type":"uint64"}],"name":"addExtension","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ccmProxy","outputs":[{"internalType":"contract CCMProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"counterpartChainId","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_ownerAddress","type":"address"},{"internalType":"bytes","name":"_swthAddress","type":"bytes"}],"name":"createWallet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receivingAddress","type":"address"},{"internalType":"address","name":"_assetHash","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"extensionTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"extensions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_ownerAddress","type":"address"},{"internalType":"bytes","name":"_swthAddress","type":"bytes"},{"internalType":"bytes32","name":"_bytecodeHash","type":"bytes32"}],"name":"getWalletAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_assetHash","type":"address"},{"internalType":"bytes","name":"_targetProxyHash","type":"bytes"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"bytes","name":"_toAssetHash","type":"bytes"},{"internalType":"bytes","name":"_feeAddress","type":"bytes"},{"internalType":"uint256[]","name":"_values","type":"uint256[]"}],"name":"lock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_walletAddress","type":"address"},{"internalType":"address","name":"_assetHash","type":"address"},{"internalType":"bytes","name":"_targetProxyHash","type":"bytes"},{"internalType":"bytes","name":"_toAssetHash","type":"bytes"},{"internalType":"bytes","name":"_feeAddress","type":"bytes"},{"internalType":"uint256[]","name":"_values","type":"uint256[]"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32[]","name":"_rs","type":"bytes32[]"}],"name":"lockFromWallet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_argsBz","type":"bytes"},{"internalType":"bytes","name":"_fromContractAddr","type":"bytes"},{"internalType":"uint64","name":"_fromChainId","type":"uint64"}],"name":"registerAsset","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"registry","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_argsBz","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"_fromChainId","type":"uint64"}],"name":"removeExtension","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"seenMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokenFallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_argsBz","type":"bytes"},{"internalType":"bytes","name":"_fromContractAddr","type":"bytes"},{"internalType":"uint64","name":"_fromChainId","type":"uint64"}],"name":"unlock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wallets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405260006001553480156200001657600080fd5b506040516200523438038062005234833981810160405260408110156200003c57600080fd5b5080516020909101516000805460ff191660011790556001600160401b038116620000995760405162461bcd60e51b8152600401808060200182810382526021815260200180620052136021913960400191505060405180910390fd5b6001600160a01b038216620000f5576040805162461bcd60e51b815260206004820152601f60248201527f63636d50726f7879416464726573732063616e6e6f7420626520656d70747900604482015290519081900360640190fd5b600080546001600160a01b0390931661010002610100600160a81b03196001600160401b03909316600160a81b02600160a81b600160e81b031990941693909317919091169190911790556150c380620001506000396000f3fe6080604052600436106101185760003560e01c80639dde57b3116100a0578063b9a08bd711610064578063b9a08bd7146109aa578063c0ee0b8a146109dd578063e2bebb6614610a6f578063eebc8e1914610b43578063f179f55514610bce5761011f565b80639dde57b31461075e578063adb610a31461093a578063ae403c641461094f578063aeed9b1614610964578063b8b5b334146109795761011f565b806337aca7f2116100e757806337aca7f21461031e5780633bd6e7f8146103f25780636c7071fb146104c65780637d7708d71461056d57806389b08f111461072b5761011f565b8063038defd71461012457806306af4b9f14610169578063086404761461025157806317a47282146102945761011f565b3661011f57005b600080fd5b34801561013057600080fd5b506101576004803603602081101561014757600080fd5b50356001600160a01b0316610bf8565b60408051918252519081900360200190f35b34801561017557600080fd5b5061023d6004803603606081101561018c57600080fd5b810190602081018135600160201b8111156101a657600080fd5b8201836020820111156101b857600080fd5b803590602001918460018302840111600160201b831117156101d957600080fd5b919390929091602081019035600160201b8111156101f657600080fd5b82018360208201111561020857600080fd5b803590602001918460018302840111600160201b8311171561022957600080fd5b9193509150356001600160401b0316610c0a565b604080519115158252519081900360200190f35b34801561025d57600080fd5b5061023d6004803603606081101561027457600080fd5b506001600160a01b03813581169160208101359091169060400135610f88565b3480156102a057600080fd5b506102a96110f6565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102e35781810151838201526020016102cb565b50505050905090810190601f1680156103105780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561032a57600080fd5b5061023d6004803603606081101561034157600080fd5b810190602081018135600160201b81111561035b57600080fd5b82018360208201111561036d57600080fd5b803590602001918460018302840111600160201b8311171561038e57600080fd5b919390929091602081019035600160201b8111156103ab57600080fd5b8201836020820111156103bd57600080fd5b803590602001918460018302840111600160201b831117156103de57600080fd5b9193509150356001600160401b031661112f565b3480156103fe57600080fd5b5061023d6004803603606081101561041557600080fd5b810190602081018135600160201b81111561042f57600080fd5b82018360208201111561044157600080fd5b803590602001918460018302840111600160201b8311171561046257600080fd5b919390929091602081019035600160201b81111561047f57600080fd5b82018360208201111561049157600080fd5b803590602001918460018302840111600160201b831117156104b257600080fd5b9193509150356001600160401b031661135b565b3480156104d257600080fd5b50610551600480360360608110156104e957600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561051357600080fd5b82018360208201111561052557600080fd5b803590602001918460018302840111600160201b8311171561054657600080fd5b919350915035611566565b604080516001600160a01b039092168252519081900360200190f35b61023d600480360360c081101561058357600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105ad57600080fd5b8201836020820111156105bf57600080fd5b803590602001918460018302840111600160201b831117156105e057600080fd5b919390929091602081019035600160201b8111156105fd57600080fd5b82018360208201111561060f57600080fd5b803590602001918460018302840111600160201b8311171561063057600080fd5b919390929091602081019035600160201b81111561064d57600080fd5b82018360208201111561065f57600080fd5b803590602001918460018302840111600160201b8311171561068057600080fd5b919390929091602081019035600160201b81111561069d57600080fd5b8201836020820111156106af57600080fd5b803590602001918460018302840111600160201b831117156106d057600080fd5b919390929091602081019035600160201b8111156106ed57600080fd5b8201836020820111156106ff57600080fd5b803590602001918460208302840111600160201b8311171561072057600080fd5b509092509050611602565b34801561073757600080fd5b5061023d6004803603602081101561074e57600080fd5b50356001600160a01b03166117b7565b34801561076a57600080fd5b5061023d600480360361010081101561078257600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156107b557600080fd5b8201836020820111156107c757600080fd5b803590602001918460018302840111600160201b831117156107e857600080fd5b919390929091602081019035600160201b81111561080557600080fd5b82018360208201111561081757600080fd5b803590602001918460018302840111600160201b8311171561083857600080fd5b919390929091602081019035600160201b81111561085557600080fd5b82018360208201111561086757600080fd5b803590602001918460018302840111600160201b8311171561088857600080fd5b919390929091602081019035600160201b8111156108a557600080fd5b8201836020820111156108b757600080fd5b803590602001918460208302840111600160201b831117156108d857600080fd5b9193909260ff83351692604081019060200135600160201b8111156108fc57600080fd5b82018360208201111561090e57600080fd5b803590602001918460208302840111600160201b8311171561092f57600080fd5b5090925090506117cc565b34801561094657600080fd5b50610157611ca6565b34801561095b57600080fd5b50610551611cac565b34801561097057600080fd5b50610551611cb1565b34801561098557600080fd5b5061098e611cc5565b604080516001600160401b039092168252519081900360200190f35b3480156109b657600080fd5b5061023d600480360360208110156109cd57600080fd5b50356001600160a01b0316611cdb565b3480156109e957600080fd5b50610a6d60048036036060811015610a0057600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610a2f57600080fd5b820183602082011115610a4157600080fd5b803590602001918460018302840111600160201b83111715610a6257600080fd5b509092509050611cf0565b005b348015610a7b57600080fd5b5061023d60048036036060811015610a9257600080fd5b810190602081018135600160201b811115610aac57600080fd5b820183602082011115610abe57600080fd5b803590602001918460018302840111600160201b83111715610adf57600080fd5b919390929091602081019035600160201b811115610afc57600080fd5b820183602082011115610b0e57600080fd5b803590602001918460018302840111600160201b83111715610b2f57600080fd5b9193509150356001600160401b0316611cf6565b348015610b4f57600080fd5b5061023d60048036036040811015610b6657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b811115610b9057600080fd5b820183602082011115610ba257600080fd5b803590602001918460018302840111600160201b83111715610bc357600080fd5b509092509050611f02565b348015610bda57600080fd5b5061023d60048036036020811015610bf157600080fd5b5035612130565b60026020526000908152604090205481565b60008060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c5957600080fd5b505afa158015610c6d573d6000803e3d6000fd5b505050506040513d6020811015610c8357600080fd5b50516001600160a01b03163314610cd9576040805162461bcd60e51b81526020600482015260156024820152746d73672e73656e646572206973206e6f742043434d60581b604482015290519081900360640190fd5b60005460ff16610d1e576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff1916908190556001600160401b03838116600160a81b9092041614610d83576040805162461bcd60e51b815260206004820152601060248201526f125b9d985b1a590818da185a5b88125160821b604482015290519081900360640190fd5b610d8b614516565b610dca87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061214592505050565b805151909150610e19576040805162461bcd60e51b8152602060048201526015602482015274092dcecc2d8d2c840cce4deda82e6e6cae890c2e6d605b1b604482015290519081900360640190fd5b806020015151601414610e69576040805162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e8de82e6e6cae890c2e6d606b1b604482015290519081900360640190fd5b6000610e7882602001516121a7565b90506000610e8983604001516121a7565b9050610ece8288888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050875191506121f19050565b610edd8183856060015161236a565b7f2d3f6ad356f1c408166244c68a928a722472299760d71a6de97f6057b912972c828285606001518c8c60405180866001600160a01b03168152602001856001600160a01b03168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039850909650505050505050a1600193505050506000805460ff1916600117905595945050505050565b3360009081526004602052604081205460ff161515600114610fe5576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21032bc3a32b739b4b7b760791b604482015290519081900360640190fd5b6001600160a01b038316611095576040516000906001600160a01b0386169084908381818185875af1925050503d806000811461103e576040519150601f19603f3d011682016040523d82523d6000602084013e611043565b606091505b505090508061108b576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b60019150506110ef565b604080516001600160a01b038616602482015260448082018590528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905283906110e990829061246f565b60019150505b9392505050565b6040518060400160405280601e81526020017f737769746368656f2d6574682d77616c6c65742d666163746f72792d7631000081525081565b60008060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561117e57600080fd5b505afa158015611192573d6000803e3d6000fd5b505050506040513d60208110156111a857600080fd5b50516001600160a01b031633146111fe576040805162461bcd60e51b81526020600482015260156024820152746d73672e73656e646572206973206e6f742043434d60581b604482015290519081900360640190fd5b60005460ff16611243576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff1916908190556001600160401b03838116600160a81b90920416146112a8576040805162461bcd60e51b815260206004820152601060248201526f125b9d985b1a590818da185a5b88125160821b604482015290519081900360640190fd5b6112b061455b565b6112ef87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061261e92505050565b905061134061130182602001516121a7565b86868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050855191506126569050565b60019150506000805460ff1916600117905595945050505050565b60008060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113aa57600080fd5b505afa1580156113be573d6000803e3d6000fd5b505050506040513d60208110156113d457600080fd5b50516001600160a01b0316331461142a576040805162461bcd60e51b81526020600482015260156024820152746d73672e73656e646572206973206e6f742043434d60581b604482015290519081900360640190fd5b60005460ff1661146f576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff1916908190556001600160401b03838116600160a81b90920416146114d4576040805162461bcd60e51b815260206004820152601060248201526f125b9d985b1a590818da185a5b88125160821b604482015290519081900360640190fd5b6114dc614575565b61151b87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127e992505050565b9050600061152c82600001516121a7565b6001600160a01b031660009081526004602052604081208054600160ff199182168117909255825416811790915598975050505050505050565b6000806115a98686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061280f92505050565b604080516001600160f81b03196020808301919091523060601b6021830152603582019390935260558082019690965281518082039096018652607501905283519301929092206001600160a01b031695945050505050565b6000805460ff16611648576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff19168155611683908d90859085908161166357fe5b905060200201358585600281811061167757fe5b9050602002013561291f565b6117988c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b9081908401838280828437600081840152601f19601f820116905080830192505050505050508c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508b93508a925090508161174157fe5b905060200201358888600181811061175557fe5b905060200201358b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b0692505050565b5060016000805460ff191660011790559b9a5050505050505050505050565b60056020526000908152604090205460ff1681565b6000805460ff16611812576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff191681556001600160a01b038f1681526005602052604090205460ff1661187f576040805162461bcd60e51b8152602060048201526016602482015275496e76616c69642077616c6c6574206164647265737360501b604482015290519081900360640190fd5b60008e9050611a47816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156118c057600080fd5b505afa1580156118d4573d6000803e3d6000fd5b505050506040513d60208110156118ea57600080fd5b81019080805190602001909291905050508f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061309e92505050565b611a798f8f89896000818110611a5957fe5b905060200201358a8a6003818110611a6d57fe5b905060200201356132d4565b611c838e8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805163f445b6f360e01b815290516001600160a01b038b16955063f445b6f39450600480830194509091829003018186803b158015611b3457600080fd5b505afa158015611b48573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015611b7157600080fd5b8101908080516040519392919084600160201b821115611b9057600080fd5b908301906020820185811115611ba557600080fd5b8251600160201b811182820188101715611bbe57600080fd5b82525081516020918201929091019080838360005b83811015611beb578181015183820152602001611bd3565b50505050905090810190601f168015611c185780820380516001836020036101000a031916815260200191505b506040525050508b8b6000818110611c2c57fe5b905060200201358c8c6001818110611c4057fe5b905060200201358f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b0692505050565b60019150506000805460ff191660011790559d9c50505050505050505050505050565b60015481565b600081565b60005461010090046001600160a01b031681565b600054600160a81b90046001600160401b031681565b60046020526000908152604090205460ff1681565b50505050565b60008060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d4557600080fd5b505afa158015611d59573d6000803e3d6000fd5b505050506040513d6020811015611d6f57600080fd5b50516001600160a01b03163314611dc5576040805162461bcd60e51b81526020600482015260156024820152746d73672e73656e646572206973206e6f742043434d60581b604482015290519081900360640190fd5b60005460ff16611e0a576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff1916908190556001600160401b03838116600160a81b9092041614611e6f576040805162461bcd60e51b815260206004820152601060248201526f125b9d985b1a590818da185a5b88125160821b604482015290519081900360640190fd5b611e77614575565b611eb687878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127e992505050565b90506000611ec782600001516121a7565b6001600160a01b03166000908152600460205260409020805460ff191690555060019150506000805460ff1916600117905595945050505050565b6000805460ff16611f48576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff191690556001600160a01b038416611fa2576040805162461bcd60e51b8152602060048201526012602482015271456d707479206f776e65724164647265737360701b604482015290519081900360640190fd5b81611fe8576040805162461bcd60e51b8152602060048201526011602482015270456d70747920737774684164647265737360781b604482015290519081900360640190fd5b600061202a8585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061280f92505050565b905060008160405161203b90614588565b8190604051809103906000f590508015801561205b573d6000803e3d6000fd5b509050806001600160a01b031663d1f578948787876040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b1580156120e157600080fd5b505af11580156120f5573d6000803e3d6000fd5b505050506001600160a01b031660009081526005602052604081208054600160ff199182168117909255825416811790915595945050505050565b60036020526000908152604090205460ff1681565b61214d614516565b612155614516565b60006121618482613524565b90835290506121708482613524565b602084019190915290506121848482613524565b6040840191909152905061219884826135fc565b5060608301525090505b919050565b600081516014146121e95760405162461bcd60e51b8152600401808060200182810382526023815260200180614ef96023913960400191505060405180910390fd5b506014015190565b815160141461223e576040805162461bcd60e51b8152602060048201526014602482015273496e76616c69642070726f78794164647265737360601b604482015290519081900360640190fd5b600082826040516020018083805190602001908083835b602083106122745780518252601f199092019160209182019101612255565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106122bc5780518252601f19909201916020918201910161229d565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040528051906020012090508060026000866001600160a01b03166001600160a01b031681526020019081526020016000205414611cf0576040805162461bcd60e51b8152602060048201526014602482015273105cdcd95d081b9bdd081c9959da5cdd195c995960621b604482015290519081900360640190fd5b6001600160a01b038216612416576040516000906001600160a01b0385169083908381818185875af1925050503d80600081146123c3576040519150601f19603f3d011682016040523d82523d6000602084013e6123c8565b606091505b5050905080612410576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b5061246a565b604080516001600160a01b038516602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790528290611cf090829061246f565b505050565b612478826136f9565b6124c9576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106125075780518252601f1990920191602091820191016124e8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612569576040519150601f19603f3d011682016040523d82523d6000602084013e61256e565b606091505b5091509150816125c5576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611cf0578080602001905160208110156125e157600080fd5b5051611cf05760405162461bcd60e51b815260040180806020018281038252602a815260200180614f6d602a913960400191505060405180910390fd5b61262661455b565b61262e61455b565b600061263a8482613524565b90835290506126498482613524565b5060208301525092915050565b81516014146126a3576040805162461bcd60e51b8152602060048201526014602482015273496e76616c69642070726f78794164647265737360601b604482015290519081900360640190fd5b6001600160a01b0383166000908152600260205260409020541561270e576040805162461bcd60e51b815260206004820152601860248201527f417373657420616c726561647920726567697374657265640000000000000000604482015290519081900360640190fd5b600082826040516020018083805190602001908083835b602083106127445780518252601f199092019160209182019101612725565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061278c5780518252601f19909201916020918201910161276d565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835284528151918101919091206001600160a01b039a909a1660009081526002909152919091209790975550505050505050565b6127f1614575565b6127f9614575565b60006128058482613524565b5082525092915050565b60006040518060400160405280601e81526020017f737769746368656f2d6574682d77616c6c65742d666163746f72792d7631000081525083836040516020018084805190602001908083835b6020831061287b5780518252601f19909201916020918201910161285c565b6001836020036101000a038019825116818451168082178552505050505050905001836001600160a01b031660601b815260140182805190602001908083835b602083106128da5780518252601f1990920191602091820191016128bb565b6001836020036101000a038019825116818451168082178552505050505050905001935050505060405160208183030381529060405280519060200120905092915050565b6001600160a01b0383166129705781341461296b5760405162461bcd60e51b815260040180806020018281038252603281526020018061505c6032913960400191505060405180910390fd5b61246a565b604080516370a0823160e01b8152306004820152905184916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b1580156129bb57600080fd5b505afa1580156129cf573d6000803e3d6000fd5b505050506040513d60208110156129e557600080fd5b50516040805133602482015230604482015260648082018790528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052909150612a3990839061246f565b6000612abe82846001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612a8c57600080fd5b505afa158015612aa0573d6000803e3d6000fd5b505050506040513d6020811015612ab657600080fd5b505190613735565b9050848114612afe5760405162461bcd60e51b8152600401808060200182810382526035815260200180614fdb6035913960400191505060405180910390fd5b505050505050565b8551601414612b5c576040805162461bcd60e51b815260206004820152601760248201527f496e76616c69642074617267657450726f787948617368000000000000000000604482015290519081900360640190fd5b6000855111612ba6576040805162461bcd60e51b815260206004820152601160248201527008adae0e8f240e8de82e6e6cae890c2e6d607b1b604482015290519081900360640190fd5b6000845111612bee576040805162461bcd60e51b815260206004820152600f60248201526e456d70747920746f4164647265737360881b604482015290519081900360640190fd5b60008311612c43576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d757374206265206d6f7265207468616e207a65726f000000604482015290519081900360640190fd5b828210612c815760405162461bcd60e51b81526004018080602001828103825260288152602001806150346028913960400191505060405180910390fd5b612c8c8787876121f1565b612c94614516565b604051806101000160405280612ca98a613777565b81526020018781526020018681526020018581526020018481526020018381526020013360405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040528152602001612d05613792565b905290506060612d14826137b3565b90506000612d20613a8e565b9050806001600160a01b031663bd5cf625600060159054906101000a90046001600160401b03168b856040518463ffffffff1660e01b815260040180846001600160401b03168152602001806020018060200180602001848103845286818151815260200191508051906020019080838360005b83811015612dac578181015183820152602001612d94565b50505050905090810190601f168015612dd95780820380516001836020036101000a031916815260200191505b508481038352600681526020018065756e6c6f636b60d01b815250602001848103825285818151815260200191508051906020019080838360005b83811015612e2c578181015183820152602001612e14565b50505050905090810190601f168015612e595780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b158015612e7c57600080fd5b505af1158015612e90573d6000803e3d6000fd5b505050506040513d6020811015612ea657600080fd5b5051612ee35760405162461bcd60e51b815260040180806020018281038252602f815260200180614f1c602f913960400191505060405180910390fd5b7f3aa1a37a3bb16943a2c97dd810c5601a4ce19bb1942a54401f821af5515c55308a33600060159054906101000a90046001600160401b03168b8b8760405180876001600160a01b03168152602001866001600160a01b03168152602001856001600160401b03168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b83811015612f91578181015183820152602001612f79565b50505050905090810190601f168015612fbe5780820380516001836020036101000a031916815260200191505b50848103835286518152865160209182019188019080838360005b83811015612ff1578181015183820152602001612fd9565b50505050905090810190601f16801561301e5780820380516001836020036101000a031916815260200191505b50848103825285518152855160209182019187019080838360005b83811015613051578181015183820152602001613039565b50505050905090810190601f16801561307e5780820380516001836020036101000a031916815260200191505b50995050505050505050505060405180910390a150505050505050505050565b600087878787876000815181106130b157fe5b6020026020010151886001815181106130c657fe5b6020026020010151896002815181106130db57fe5b602002602001015160405160200180806973656e64546f6b656e7360b01b815250600a01886001600160a01b031660601b815260140187805190602001908083835b6020831061313c5780518252601f19909201916020918201910161311d565b51815160209384036101000a600019018019909216911617905289519190930192890191508083835b602083106131845780518252601f199092019160209182019101613165565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b602083106131cc5780518252601f1990920191602091820191016131ad565b51815160209384036101000a6000190180199092169116179052920195865250848101939093525060408084019190915280518084038201815260609093018152825192820192909220600081815260039092529190205490955060ff1615935061327992505050576040805162461bcd60e51b815260206004820152601460248201527326b2b9b9b0b3b29030b63932b0b23c9039b2b2b760611b604482015290519081900360640190fd5b6000818152600360205260408120805460ff1916600117905582516132c99183918c9187918791906132a757fe5b6020026020010151866001815181106132bc57fe5b6020026020010151613b11565b505050505050505050565b836001600160a01b0384166133a3576000479050816001600160a01b0316631570f3f8846040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561332e57600080fd5b505af1158015613342573d6000803e3d6000fd5b50505050600061335b824761373590919063ffffffff16565b905084811461339b5760405162461bcd60e51b815260040180806020018281038252603281526020018061505c6032913960400191505060405180910390fd5b505050611cf0565b604080516370a0823160e01b8152306004820152905185916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b1580156133ee57600080fd5b505afa158015613402573d6000803e3d6000fd5b505050506040513d602081101561341857600080fd5b505160408051637c2c671b60e01b81526001600160a01b03898116600483015260248201889052915192935090851691637c2c671b9160448082019260009290919082900301818387803b15801561346f57600080fd5b505af1158015613483573d6000803e3d6000fd5b5050505060006134da82846001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612a8c57600080fd5b905085811461351a5760405162461bcd60e51b8152600401808060200182810382526035815260200180614fdb6035913960400191505060405180910390fd5b5050505050505050565b60606000806135338585613c17565b86519095509091508185011180159061354d575080840184105b6135885760405162461bcd60e51b81526004018080602001828103825260248152602001806150106024913960400191505060405180910390fd5b6060811580156135a3576040519150602082016040526135ed565b6040519150601f8316801560200281840101848101888315602002848c0101015b818310156135dc5780518352602092830192016135c4565b5050848452601f01601f1916604052505b509250830190505b9250929050565b6000808351836020011115801561361557508260200183105b6136505760405162461bcd60e51b8152600401808060200182810382526023815260200180614ed66023913960400191505060405180910390fd5b600060405160206000600182038760208a0101515b838310156136855780821a83860153600183019250600182039150613665565b50505081016040525190506001600160ff1b038111156136ec576040805162461bcd60e51b815260206004820152601760248201527f56616c75652065786365656473207468652072616e6765000000000000000000604482015290519081900360640190fd5b9460209390930193505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061372d57508115155b949350505050565b60006110ef83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613e30565b604080516014815260609290921b6020830152818101905290565b60006137a960018054613ec790919063ffffffff16565b6001819055905090565b6060806137c38360000151613f21565b6137d08460200151613f21565b6137dd8560400151613f21565b6137ea8660600151613fe7565b6137f78760800151613fe7565b6138048860a00151613f21565b6138118960c00151613f21565b61381e8a60e00151613fe7565b6040516020018089805190602001908083835b602083106138505780518252601f199092019160209182019101613831565b51815160209384036101000a60001901801990921691161790528b5191909301928b0191508083835b602083106138985780518252601f199092019160209182019101613879565b51815160209384036101000a60001901801990921691161790528a5191909301928a0191508083835b602083106138e05780518252601f1990920191602091820191016138c1565b51815160209384036101000a600019018019909216911617905289519190930192890191508083835b602083106139285780518252601f199092019160209182019101613909565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b602083106139705780518252601f199092019160209182019101613951565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106139b85780518252601f199092019160209182019101613999565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b60208310613a005780518252601f1990920191602091820191016139e1565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310613a485780518252601f199092019160209182019101613a29565b6001836020036101000a03801982511681845116808217855250505050505090500198505050505050505050604051602081830303815290604052905080915050919050565b600080600060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b158015613adf57600080fd5b505afa158015613af3573d6000803e3d6000fd5b505050506040513d6020811015613b0957600080fd5b505191505090565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c80830189905283518084039091018152605c83018085528151918301919091206000909152607c830180855281905260ff8716609c84015260bc830186905260dc8301859052925160019260fc8082019392601f1981019281900390910190855afa158015613bb4573d6000803e3d6000fd5b505050602060405103516001600160a01b0316856001600160a01b031614612afe576040805162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b604482015290519081900360640190fd5b6000806000613c268585614084565b94509050600060fd60f81b6001600160f81b031983161415613cc457613c4c8686614102565b955061ffff16905060fd8110801590613c67575061ffff8111155b613cb8576040805162461bcd60e51b815260206004820152601f60248201527f4e65787455696e7431362c2076616c7565206f7574736964652072616e676500604482015290519081900360640190fd5b92508391506135f59050565b607f60f91b6001600160f81b031983161415613d5457613ce4868661418b565b955063ffffffff16905061ffff81118015613d03575063ffffffff8111155b613cb8576040805162461bcd60e51b815260206004820181905260248201527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604482015290519081900360640190fd5b6001600160f81b03198083161415613dd557613d708686614231565b95506001600160401b0316905063ffffffff8111613cb8576040805162461bcd60e51b815260206004820181905260248201527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604482015290519081900360640190fd5b5060f881901c60fd8110613cb8576040805162461bcd60e51b815260206004820181905260248201527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604482015290519081900360640190fd5b60008184841115613ebf5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613e84578181015183820152602001613e6c565b50505050905090810190601f168015613eb15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000828201838110156110ef576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b8051606090613f2f816142d7565b836040516020018083805190602001908083835b60208310613f625780518252601f199092019160209182019101613f43565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310613faa5780518252601f199092019160209182019101613f8b565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052915050919050565b60606001600160ff1b03821115614045576040805162461bcd60e51b815260206004820152601b60248201527f56616c756520657863656564732075696e743235352072616e67650000000000604482015290519081900360640190fd5b60405160208082526000601f5b828210156140745785811a826020860101536001919091019060001901614052565b5050506040818101905292915050565b6000808351836001011115801561409d57508260010183105b6140ee576040805162461bcd60e51b815260206004820181905260248201527f4e657874427974652c204f66667365742065786365656473206d6178696d756d604482015290519081900360640190fd5b505081810160200151600182019250929050565b6000808351836002011115801561411b57508260020183105b6141565760405162461bcd60e51b8152600401808060200182810382526022815260200180614f4b6022913960400191505060405180910390fd5b6000604051846020870101518060011a82538060001a6001830153506002818101604052601d19909101519694019450505050565b600080835183600401111580156141a457508260040183105b6141df5760405162461bcd60e51b8152600401808060200182810382526022815260200180614fb96022913960400191505060405180910390fd5b600060405160046000600182038760208a0101515b838310156142145780821a838601536001830192506001820391506141f4565b505050808201604052602003900351956004949094019450505050565b6000808351836008011115801561424a57508260080183105b6142855760405162461bcd60e51b8152600401808060200182810382526022815260200180614f976022913960400191505060405180910390fd5b600060405160086000600182038760208a0101515b838310156142ba5780821a8386015360018301925060018203915061429a565b505050808201604052602003900351956008949094019450505050565b606060fd826001600160401b031610156142fb576142f48261441d565b90506121a2565b61ffff826001600160401b0316116143d95761431a60fd60f81b614439565b6143238361444d565b6040516020018083805190602001908083835b602083106143555780518252601f199092019160209182019101614336565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061439d5780518252601f19909201916020918201910161437e565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405290506121a2565b63ffffffff826001600160401b031611614403576143fa607f60f91b614439565b61432383614490565b6144146001600160f81b0319614439565b614323836144d3565b604080516001815260f89290921b602083015260218201905290565b60606144478260f81c61441d565b92915050565b6040516002808252606091906000601f5b828210156144805785811a82602086010153600191909101906000190161445e565b5050506022810160405292915050565b6040516004808252606091906000601f5b828210156144c35785811a8260208601015360019190910190600019016144a1565b5050506024810160405292915050565b6040516008808252606091906000601f5b828210156145065785811a8260208601015360019190910190600019016144e4565b5050506028810160405292915050565b60405180610100016040528060608152602001606081526020016060815260200160008152602001600081526020016060815260200160608152602001600081525090565b604051806040016040528060608152602001606081525090565b6040518060200160405280606081525090565b610920806145968339019056fe608060405234801561001057600080fd5b50610900806100206000396000f3fe60806040526004361061007f5760003560e01c80638da5cb5b1161004e5780638da5cb5b1461014a578063c0ee0b8a1461015f578063d1f57894146101f1578063f445b6f31461027e57610086565b806302d05d3f1461008b5780631570f3f8146100bc578063392e53cd146100e85780637c2c671b1461011157610086565b3661008657005b600080fd5b34801561009757600080fd5b506100a0610308565b604080516001600160a01b039092168252519081900360200190f35b3480156100c857600080fd5b506100e6600480360360208110156100df57600080fd5b503561031c565b005b3480156100f457600080fd5b506100fd61041b565b604080519115158252519081900360200190f35b34801561011d57600080fd5b506100e66004803603604081101561013457600080fd5b506001600160a01b038135169060200135610424565b34801561015657600080fd5b506100a06104e3565b34801561016b57600080fd5b506100e66004803603606081101561018257600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156101b257600080fd5b8201836020820111156101c457600080fd5b803590602001918460018302840111640100000000831117156101e657600080fd5b5090925090506104f2565b3480156101fd57600080fd5b506100e66004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b5090925090506104f8565b34801561028a57600080fd5b50610293610597565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102cd5781810151838201526020016102b5565b50505050905090810190601f1680156102fa5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60005461010090046001600160a01b031681565b60005461010090046001600160a01b03163314610379576040805162461bcd60e51b815260206004820152601660248201527529b2b73232b91036bab9ba1031329031b932b0ba37b960511b604482015290519081900360640190fd5b600080546040516101009091046001600160a01b03169083908381818185875af1925050503d80600081146103ca576040519150601f19603f3d011682016040523d82523d6000602084013e6103cf565b606091505b5050905080610417576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b5050565b60005460ff1681565b60005461010090046001600160a01b03163314610481576040805162461bcd60e51b815260206004820152601660248201527529b2b73232b91036bab9ba1031329031b932b0ba37b960511b604482015290519081900360640190fd5b600054604080516101009092046001600160a01b031660248301526044808301849052815180840390910181526064909201905260208101805163a9059cbb60e01b6001600160e01b0390911617905282906104de908290610622565b505050565b6001546001600160a01b031681565b50505050565b60005460ff1615610550576040805162461bcd60e51b815260206004820152601c60248201527f436f6e747261637420616c726561647920696e697469616c697a656400000000604482015290519081900360640190fd5b60008054600160ff199091168117610100600160a81b03191661010033021790915580546001600160a01b0319166001600160a01b0385161790556104f26002838361080d565b6002805460408051602060018416156101000260001901909316849004601f8101849004840282018401909252818152929183018282801561061a5780601f106105ef5761010080835404028352916020019161061a565b820191906000526020600020905b8154815290600101906020018083116105fd57829003601f168201915b505050505081565b61062b826107d1565b61067c576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106106ba5780518252601f19909201916020918201910161069b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461071c576040519150601f19603f3d011682016040523d82523d6000602084013e610721565b606091505b509150915081610778576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156104f25780806020019051602081101561079457600080fd5b50516104f25760405162461bcd60e51b815260040180806020018281038252602a8152602001806108a1602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061080557508115155b949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061084e5782800160ff1982351617855561087b565b8280016001018555821561087b579182015b8281111561087b578235825591602001919060010190610860565b5061088792915061088b565b5090565b5b80821115610887576000815560010161088c56fe5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122010e645043ba7055fb1ee83b35aafd81099f38b704b7bb09dab330ec96206a4f764736f6c634300060c00335265656e7472616e637947756172643a207265656e7472616e742063616c6c004e65787455696e743235352c206f66667365742065786365656473206d6178696d756d6279746573206c656e67746820646f6573206e6f74206d61746368206164647265737345746843726f7373436861696e4d616e616765722063726f7373436861696e206578656375746564206572726f72214e65787455696e7431362c206f66667365742065786365656473206d6178696d756d5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644e65787455696e7436342c206f66667365742065786365656473206d6178696d756d4e65787455696e7433322c206f66667365742065786365656473206d6178696d756d546f6b656e73207472616e7366657272656420646f6573206e6f74206d617463682074686520657870656374656420616d6f756e744e65787456617242797465732c206f66667365742065786365656473206d6178696d756d46656520616d6f756e742063616e6e6f742062652067726561746572207468616e20616d6f756e74455448207472616e7366657272656420646f6573206e6f74206d617463682074686520657870656374656420616d6f756e74a2646970667358221220cf7112f021f9e2524cc4412d735952b2778a93a00ac3ae2b1657c7f00496535764736f6c634300060c0033636f756e74657270617274436861696e49642063616e6e6f74206265207a65726f0000000000000000000000005a51e2ebf8d136926b9ca7b59b60464e7c44d2eb0000000000000000000000000000000000000000000000000000000000000005
Deployed Bytecode
0x6080604052600436106101185760003560e01c80639dde57b3116100a0578063b9a08bd711610064578063b9a08bd7146109aa578063c0ee0b8a146109dd578063e2bebb6614610a6f578063eebc8e1914610b43578063f179f55514610bce5761011f565b80639dde57b31461075e578063adb610a31461093a578063ae403c641461094f578063aeed9b1614610964578063b8b5b334146109795761011f565b806337aca7f2116100e757806337aca7f21461031e5780633bd6e7f8146103f25780636c7071fb146104c65780637d7708d71461056d57806389b08f111461072b5761011f565b8063038defd71461012457806306af4b9f14610169578063086404761461025157806317a47282146102945761011f565b3661011f57005b600080fd5b34801561013057600080fd5b506101576004803603602081101561014757600080fd5b50356001600160a01b0316610bf8565b60408051918252519081900360200190f35b34801561017557600080fd5b5061023d6004803603606081101561018c57600080fd5b810190602081018135600160201b8111156101a657600080fd5b8201836020820111156101b857600080fd5b803590602001918460018302840111600160201b831117156101d957600080fd5b919390929091602081019035600160201b8111156101f657600080fd5b82018360208201111561020857600080fd5b803590602001918460018302840111600160201b8311171561022957600080fd5b9193509150356001600160401b0316610c0a565b604080519115158252519081900360200190f35b34801561025d57600080fd5b5061023d6004803603606081101561027457600080fd5b506001600160a01b03813581169160208101359091169060400135610f88565b3480156102a057600080fd5b506102a96110f6565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102e35781810151838201526020016102cb565b50505050905090810190601f1680156103105780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561032a57600080fd5b5061023d6004803603606081101561034157600080fd5b810190602081018135600160201b81111561035b57600080fd5b82018360208201111561036d57600080fd5b803590602001918460018302840111600160201b8311171561038e57600080fd5b919390929091602081019035600160201b8111156103ab57600080fd5b8201836020820111156103bd57600080fd5b803590602001918460018302840111600160201b831117156103de57600080fd5b9193509150356001600160401b031661112f565b3480156103fe57600080fd5b5061023d6004803603606081101561041557600080fd5b810190602081018135600160201b81111561042f57600080fd5b82018360208201111561044157600080fd5b803590602001918460018302840111600160201b8311171561046257600080fd5b919390929091602081019035600160201b81111561047f57600080fd5b82018360208201111561049157600080fd5b803590602001918460018302840111600160201b831117156104b257600080fd5b9193509150356001600160401b031661135b565b3480156104d257600080fd5b50610551600480360360608110156104e957600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561051357600080fd5b82018360208201111561052557600080fd5b803590602001918460018302840111600160201b8311171561054657600080fd5b919350915035611566565b604080516001600160a01b039092168252519081900360200190f35b61023d600480360360c081101561058357600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105ad57600080fd5b8201836020820111156105bf57600080fd5b803590602001918460018302840111600160201b831117156105e057600080fd5b919390929091602081019035600160201b8111156105fd57600080fd5b82018360208201111561060f57600080fd5b803590602001918460018302840111600160201b8311171561063057600080fd5b919390929091602081019035600160201b81111561064d57600080fd5b82018360208201111561065f57600080fd5b803590602001918460018302840111600160201b8311171561068057600080fd5b919390929091602081019035600160201b81111561069d57600080fd5b8201836020820111156106af57600080fd5b803590602001918460018302840111600160201b831117156106d057600080fd5b919390929091602081019035600160201b8111156106ed57600080fd5b8201836020820111156106ff57600080fd5b803590602001918460208302840111600160201b8311171561072057600080fd5b509092509050611602565b34801561073757600080fd5b5061023d6004803603602081101561074e57600080fd5b50356001600160a01b03166117b7565b34801561076a57600080fd5b5061023d600480360361010081101561078257600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156107b557600080fd5b8201836020820111156107c757600080fd5b803590602001918460018302840111600160201b831117156107e857600080fd5b919390929091602081019035600160201b81111561080557600080fd5b82018360208201111561081757600080fd5b803590602001918460018302840111600160201b8311171561083857600080fd5b919390929091602081019035600160201b81111561085557600080fd5b82018360208201111561086757600080fd5b803590602001918460018302840111600160201b8311171561088857600080fd5b919390929091602081019035600160201b8111156108a557600080fd5b8201836020820111156108b757600080fd5b803590602001918460208302840111600160201b831117156108d857600080fd5b9193909260ff83351692604081019060200135600160201b8111156108fc57600080fd5b82018360208201111561090e57600080fd5b803590602001918460208302840111600160201b8311171561092f57600080fd5b5090925090506117cc565b34801561094657600080fd5b50610157611ca6565b34801561095b57600080fd5b50610551611cac565b34801561097057600080fd5b50610551611cb1565b34801561098557600080fd5b5061098e611cc5565b604080516001600160401b039092168252519081900360200190f35b3480156109b657600080fd5b5061023d600480360360208110156109cd57600080fd5b50356001600160a01b0316611cdb565b3480156109e957600080fd5b50610a6d60048036036060811015610a0057600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610a2f57600080fd5b820183602082011115610a4157600080fd5b803590602001918460018302840111600160201b83111715610a6257600080fd5b509092509050611cf0565b005b348015610a7b57600080fd5b5061023d60048036036060811015610a9257600080fd5b810190602081018135600160201b811115610aac57600080fd5b820183602082011115610abe57600080fd5b803590602001918460018302840111600160201b83111715610adf57600080fd5b919390929091602081019035600160201b811115610afc57600080fd5b820183602082011115610b0e57600080fd5b803590602001918460018302840111600160201b83111715610b2f57600080fd5b9193509150356001600160401b0316611cf6565b348015610b4f57600080fd5b5061023d60048036036040811015610b6657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b811115610b9057600080fd5b820183602082011115610ba257600080fd5b803590602001918460018302840111600160201b83111715610bc357600080fd5b509092509050611f02565b348015610bda57600080fd5b5061023d60048036036020811015610bf157600080fd5b5035612130565b60026020526000908152604090205481565b60008060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c5957600080fd5b505afa158015610c6d573d6000803e3d6000fd5b505050506040513d6020811015610c8357600080fd5b50516001600160a01b03163314610cd9576040805162461bcd60e51b81526020600482015260156024820152746d73672e73656e646572206973206e6f742043434d60581b604482015290519081900360640190fd5b60005460ff16610d1e576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff1916908190556001600160401b03838116600160a81b9092041614610d83576040805162461bcd60e51b815260206004820152601060248201526f125b9d985b1a590818da185a5b88125160821b604482015290519081900360640190fd5b610d8b614516565b610dca87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061214592505050565b805151909150610e19576040805162461bcd60e51b8152602060048201526015602482015274092dcecc2d8d2c840cce4deda82e6e6cae890c2e6d605b1b604482015290519081900360640190fd5b806020015151601414610e69576040805162461bcd60e51b8152602060048201526013602482015272092dcecc2d8d2c840e8de82e6e6cae890c2e6d606b1b604482015290519081900360640190fd5b6000610e7882602001516121a7565b90506000610e8983604001516121a7565b9050610ece8288888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050875191506121f19050565b610edd8183856060015161236a565b7f2d3f6ad356f1c408166244c68a928a722472299760d71a6de97f6057b912972c828285606001518c8c60405180866001600160a01b03168152602001856001600160a01b03168152602001848152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039850909650505050505050a1600193505050506000805460ff1916600117905595945050505050565b3360009081526004602052604081205460ff161515600114610fe5576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21032bc3a32b739b4b7b760791b604482015290519081900360640190fd5b6001600160a01b038316611095576040516000906001600160a01b0386169084908381818185875af1925050503d806000811461103e576040519150601f19603f3d011682016040523d82523d6000602084013e611043565b606091505b505090508061108b576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b60019150506110ef565b604080516001600160a01b038616602482015260448082018590528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905283906110e990829061246f565b60019150505b9392505050565b6040518060400160405280601e81526020017f737769746368656f2d6574682d77616c6c65742d666163746f72792d7631000081525081565b60008060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561117e57600080fd5b505afa158015611192573d6000803e3d6000fd5b505050506040513d60208110156111a857600080fd5b50516001600160a01b031633146111fe576040805162461bcd60e51b81526020600482015260156024820152746d73672e73656e646572206973206e6f742043434d60581b604482015290519081900360640190fd5b60005460ff16611243576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff1916908190556001600160401b03838116600160a81b90920416146112a8576040805162461bcd60e51b815260206004820152601060248201526f125b9d985b1a590818da185a5b88125160821b604482015290519081900360640190fd5b6112b061455b565b6112ef87878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061261e92505050565b905061134061130182602001516121a7565b86868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050855191506126569050565b60019150506000805460ff1916600117905595945050505050565b60008060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113aa57600080fd5b505afa1580156113be573d6000803e3d6000fd5b505050506040513d60208110156113d457600080fd5b50516001600160a01b0316331461142a576040805162461bcd60e51b81526020600482015260156024820152746d73672e73656e646572206973206e6f742043434d60581b604482015290519081900360640190fd5b60005460ff1661146f576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff1916908190556001600160401b03838116600160a81b90920416146114d4576040805162461bcd60e51b815260206004820152601060248201526f125b9d985b1a590818da185a5b88125160821b604482015290519081900360640190fd5b6114dc614575565b61151b87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127e992505050565b9050600061152c82600001516121a7565b6001600160a01b031660009081526004602052604081208054600160ff199182168117909255825416811790915598975050505050505050565b6000806115a98686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061280f92505050565b604080516001600160f81b03196020808301919091523060601b6021830152603582019390935260558082019690965281518082039096018652607501905283519301929092206001600160a01b031695945050505050565b6000805460ff16611648576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff19168155611683908d90859085908161166357fe5b905060200201358585600281811061167757fe5b9050602002013561291f565b6117988c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b9081908401838280828437600081840152601f19601f820116905080830192505050505050508c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508b93508a925090508161174157fe5b905060200201358888600181811061175557fe5b905060200201358b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b0692505050565b5060016000805460ff191660011790559b9a5050505050505050505050565b60056020526000908152604090205460ff1681565b6000805460ff16611812576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff191681556001600160a01b038f1681526005602052604090205460ff1661187f576040805162461bcd60e51b8152602060048201526016602482015275496e76616c69642077616c6c6574206164647265737360501b604482015290519081900360640190fd5b60008e9050611a47816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156118c057600080fd5b505afa1580156118d4573d6000803e3d6000fd5b505050506040513d60208110156118ea57600080fd5b81019080805190602001909291905050508f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508c8c80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061309e92505050565b611a798f8f89896000818110611a5957fe5b905060200201358a8a6003818110611a6d57fe5b905060200201356132d4565b611c838e8e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052506040805163f445b6f360e01b815290516001600160a01b038b16955063f445b6f39450600480830194509091829003018186803b158015611b3457600080fd5b505afa158015611b48573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015611b7157600080fd5b8101908080516040519392919084600160201b821115611b9057600080fd5b908301906020820185811115611ba557600080fd5b8251600160201b811182820188101715611bbe57600080fd5b82525081516020918201929091019080838360005b83811015611beb578181015183820152602001611bd3565b50505050905090810190601f168015611c185780820380516001836020036101000a031916815260200191505b506040525050508b8b6000818110611c2c57fe5b905060200201358c8c6001818110611c4057fe5b905060200201358f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b0692505050565b60019150506000805460ff191660011790559d9c50505050505050505050505050565b60015481565b600081565b60005461010090046001600160a01b031681565b600054600160a81b90046001600160401b031681565b60046020526000908152604090205460ff1681565b50505050565b60008060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d4557600080fd5b505afa158015611d59573d6000803e3d6000fd5b505050506040513d6020811015611d6f57600080fd5b50516001600160a01b03163314611dc5576040805162461bcd60e51b81526020600482015260156024820152746d73672e73656e646572206973206e6f742043434d60581b604482015290519081900360640190fd5b60005460ff16611e0a576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff1916908190556001600160401b03838116600160a81b9092041614611e6f576040805162461bcd60e51b815260206004820152601060248201526f125b9d985b1a590818da185a5b88125160821b604482015290519081900360640190fd5b611e77614575565b611eb687878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127e992505050565b90506000611ec782600001516121a7565b6001600160a01b03166000908152600460205260409020805460ff191690555060019150506000805460ff1916600117905595945050505050565b6000805460ff16611f48576040805162461bcd60e51b815260206004820152601f6024820152600080516020614eb6833981519152604482015290519081900360640190fd5b6000805460ff191690556001600160a01b038416611fa2576040805162461bcd60e51b8152602060048201526012602482015271456d707479206f776e65724164647265737360701b604482015290519081900360640190fd5b81611fe8576040805162461bcd60e51b8152602060048201526011602482015270456d70747920737774684164647265737360781b604482015290519081900360640190fd5b600061202a8585858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061280f92505050565b905060008160405161203b90614588565b8190604051809103906000f590508015801561205b573d6000803e3d6000fd5b509050806001600160a01b031663d1f578948787876040518463ffffffff1660e01b815260040180846001600160a01b03168152602001806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b1580156120e157600080fd5b505af11580156120f5573d6000803e3d6000fd5b505050506001600160a01b031660009081526005602052604081208054600160ff199182168117909255825416811790915595945050505050565b60036020526000908152604090205460ff1681565b61214d614516565b612155614516565b60006121618482613524565b90835290506121708482613524565b602084019190915290506121848482613524565b6040840191909152905061219884826135fc565b5060608301525090505b919050565b600081516014146121e95760405162461bcd60e51b8152600401808060200182810382526023815260200180614ef96023913960400191505060405180910390fd5b506014015190565b815160141461223e576040805162461bcd60e51b8152602060048201526014602482015273496e76616c69642070726f78794164647265737360601b604482015290519081900360640190fd5b600082826040516020018083805190602001908083835b602083106122745780518252601f199092019160209182019101612255565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106122bc5780518252601f19909201916020918201910161229d565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040528051906020012090508060026000866001600160a01b03166001600160a01b031681526020019081526020016000205414611cf0576040805162461bcd60e51b8152602060048201526014602482015273105cdcd95d081b9bdd081c9959da5cdd195c995960621b604482015290519081900360640190fd5b6001600160a01b038216612416576040516000906001600160a01b0385169083908381818185875af1925050503d80600081146123c3576040519150601f19603f3d011682016040523d82523d6000602084013e6123c8565b606091505b5050905080612410576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b5061246a565b604080516001600160a01b038516602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790528290611cf090829061246f565b505050565b612478826136f9565b6124c9576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106125075780518252601f1990920191602091820191016124e8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612569576040519150601f19603f3d011682016040523d82523d6000602084013e61256e565b606091505b5091509150816125c5576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611cf0578080602001905160208110156125e157600080fd5b5051611cf05760405162461bcd60e51b815260040180806020018281038252602a815260200180614f6d602a913960400191505060405180910390fd5b61262661455b565b61262e61455b565b600061263a8482613524565b90835290506126498482613524565b5060208301525092915050565b81516014146126a3576040805162461bcd60e51b8152602060048201526014602482015273496e76616c69642070726f78794164647265737360601b604482015290519081900360640190fd5b6001600160a01b0383166000908152600260205260409020541561270e576040805162461bcd60e51b815260206004820152601860248201527f417373657420616c726561647920726567697374657265640000000000000000604482015290519081900360640190fd5b600082826040516020018083805190602001908083835b602083106127445780518252601f199092019160209182019101612725565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061278c5780518252601f19909201916020918201910161276d565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835284528151918101919091206001600160a01b039a909a1660009081526002909152919091209790975550505050505050565b6127f1614575565b6127f9614575565b60006128058482613524565b5082525092915050565b60006040518060400160405280601e81526020017f737769746368656f2d6574682d77616c6c65742d666163746f72792d7631000081525083836040516020018084805190602001908083835b6020831061287b5780518252601f19909201916020918201910161285c565b6001836020036101000a038019825116818451168082178552505050505050905001836001600160a01b031660601b815260140182805190602001908083835b602083106128da5780518252601f1990920191602091820191016128bb565b6001836020036101000a038019825116818451168082178552505050505050905001935050505060405160208183030381529060405280519060200120905092915050565b6001600160a01b0383166129705781341461296b5760405162461bcd60e51b815260040180806020018281038252603281526020018061505c6032913960400191505060405180910390fd5b61246a565b604080516370a0823160e01b8152306004820152905184916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b1580156129bb57600080fd5b505afa1580156129cf573d6000803e3d6000fd5b505050506040513d60208110156129e557600080fd5b50516040805133602482015230604482015260648082018790528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052909150612a3990839061246f565b6000612abe82846001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612a8c57600080fd5b505afa158015612aa0573d6000803e3d6000fd5b505050506040513d6020811015612ab657600080fd5b505190613735565b9050848114612afe5760405162461bcd60e51b8152600401808060200182810382526035815260200180614fdb6035913960400191505060405180910390fd5b505050505050565b8551601414612b5c576040805162461bcd60e51b815260206004820152601760248201527f496e76616c69642074617267657450726f787948617368000000000000000000604482015290519081900360640190fd5b6000855111612ba6576040805162461bcd60e51b815260206004820152601160248201527008adae0e8f240e8de82e6e6cae890c2e6d607b1b604482015290519081900360640190fd5b6000845111612bee576040805162461bcd60e51b815260206004820152600f60248201526e456d70747920746f4164647265737360881b604482015290519081900360640190fd5b60008311612c43576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d757374206265206d6f7265207468616e207a65726f000000604482015290519081900360640190fd5b828210612c815760405162461bcd60e51b81526004018080602001828103825260288152602001806150346028913960400191505060405180910390fd5b612c8c8787876121f1565b612c94614516565b604051806101000160405280612ca98a613777565b81526020018781526020018681526020018581526020018481526020018381526020013360405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040528152602001612d05613792565b905290506060612d14826137b3565b90506000612d20613a8e565b9050806001600160a01b031663bd5cf625600060159054906101000a90046001600160401b03168b856040518463ffffffff1660e01b815260040180846001600160401b03168152602001806020018060200180602001848103845286818151815260200191508051906020019080838360005b83811015612dac578181015183820152602001612d94565b50505050905090810190601f168015612dd95780820380516001836020036101000a031916815260200191505b508481038352600681526020018065756e6c6f636b60d01b815250602001848103825285818151815260200191508051906020019080838360005b83811015612e2c578181015183820152602001612e14565b50505050905090810190601f168015612e595780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b158015612e7c57600080fd5b505af1158015612e90573d6000803e3d6000fd5b505050506040513d6020811015612ea657600080fd5b5051612ee35760405162461bcd60e51b815260040180806020018281038252602f815260200180614f1c602f913960400191505060405180910390fd5b7f3aa1a37a3bb16943a2c97dd810c5601a4ce19bb1942a54401f821af5515c55308a33600060159054906101000a90046001600160401b03168b8b8760405180876001600160a01b03168152602001866001600160a01b03168152602001856001600160401b03168152602001806020018060200180602001848103845287818151815260200191508051906020019080838360005b83811015612f91578181015183820152602001612f79565b50505050905090810190601f168015612fbe5780820380516001836020036101000a031916815260200191505b50848103835286518152865160209182019188019080838360005b83811015612ff1578181015183820152602001612fd9565b50505050905090810190601f16801561301e5780820380516001836020036101000a031916815260200191505b50848103825285518152855160209182019187019080838360005b83811015613051578181015183820152602001613039565b50505050905090810190601f16801561307e5780820380516001836020036101000a031916815260200191505b50995050505050505050505060405180910390a150505050505050505050565b600087878787876000815181106130b157fe5b6020026020010151886001815181106130c657fe5b6020026020010151896002815181106130db57fe5b602002602001015160405160200180806973656e64546f6b656e7360b01b815250600a01886001600160a01b031660601b815260140187805190602001908083835b6020831061313c5780518252601f19909201916020918201910161311d565b51815160209384036101000a600019018019909216911617905289519190930192890191508083835b602083106131845780518252601f199092019160209182019101613165565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b602083106131cc5780518252601f1990920191602091820191016131ad565b51815160209384036101000a6000190180199092169116179052920195865250848101939093525060408084019190915280518084038201815260609093018152825192820192909220600081815260039092529190205490955060ff1615935061327992505050576040805162461bcd60e51b815260206004820152601460248201527326b2b9b9b0b3b29030b63932b0b23c9039b2b2b760611b604482015290519081900360640190fd5b6000818152600360205260408120805460ff1916600117905582516132c99183918c9187918791906132a757fe5b6020026020010151866001815181106132bc57fe5b6020026020010151613b11565b505050505050505050565b836001600160a01b0384166133a3576000479050816001600160a01b0316631570f3f8846040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561332e57600080fd5b505af1158015613342573d6000803e3d6000fd5b50505050600061335b824761373590919063ffffffff16565b905084811461339b5760405162461bcd60e51b815260040180806020018281038252603281526020018061505c6032913960400191505060405180910390fd5b505050611cf0565b604080516370a0823160e01b8152306004820152905185916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b1580156133ee57600080fd5b505afa158015613402573d6000803e3d6000fd5b505050506040513d602081101561341857600080fd5b505160408051637c2c671b60e01b81526001600160a01b03898116600483015260248201889052915192935090851691637c2c671b9160448082019260009290919082900301818387803b15801561346f57600080fd5b505af1158015613483573d6000803e3d6000fd5b5050505060006134da82846001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015612a8c57600080fd5b905085811461351a5760405162461bcd60e51b8152600401808060200182810382526035815260200180614fdb6035913960400191505060405180910390fd5b5050505050505050565b60606000806135338585613c17565b86519095509091508185011180159061354d575080840184105b6135885760405162461bcd60e51b81526004018080602001828103825260248152602001806150106024913960400191505060405180910390fd5b6060811580156135a3576040519150602082016040526135ed565b6040519150601f8316801560200281840101848101888315602002848c0101015b818310156135dc5780518352602092830192016135c4565b5050848452601f01601f1916604052505b509250830190505b9250929050565b6000808351836020011115801561361557508260200183105b6136505760405162461bcd60e51b8152600401808060200182810382526023815260200180614ed66023913960400191505060405180910390fd5b600060405160206000600182038760208a0101515b838310156136855780821a83860153600183019250600182039150613665565b50505081016040525190506001600160ff1b038111156136ec576040805162461bcd60e51b815260206004820152601760248201527f56616c75652065786365656473207468652072616e6765000000000000000000604482015290519081900360640190fd5b9460209390930193505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061372d57508115155b949350505050565b60006110ef83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613e30565b604080516014815260609290921b6020830152818101905290565b60006137a960018054613ec790919063ffffffff16565b6001819055905090565b6060806137c38360000151613f21565b6137d08460200151613f21565b6137dd8560400151613f21565b6137ea8660600151613fe7565b6137f78760800151613fe7565b6138048860a00151613f21565b6138118960c00151613f21565b61381e8a60e00151613fe7565b6040516020018089805190602001908083835b602083106138505780518252601f199092019160209182019101613831565b51815160209384036101000a60001901801990921691161790528b5191909301928b0191508083835b602083106138985780518252601f199092019160209182019101613879565b51815160209384036101000a60001901801990921691161790528a5191909301928a0191508083835b602083106138e05780518252601f1990920191602091820191016138c1565b51815160209384036101000a600019018019909216911617905289519190930192890191508083835b602083106139285780518252601f199092019160209182019101613909565b51815160209384036101000a600019018019909216911617905288519190930192880191508083835b602083106139705780518252601f199092019160209182019101613951565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b602083106139b85780518252601f199092019160209182019101613999565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b60208310613a005780518252601f1990920191602091820191016139e1565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310613a485780518252601f199092019160209182019101613a29565b6001836020036101000a03801982511681845116808217855250505050505090500198505050505050505050604051602081830303815290604052905080915050919050565b600080600060019054906101000a90046001600160a01b03166001600160a01b03166387939a7f6040518163ffffffff1660e01b815260040160206040518083038186803b158015613adf57600080fd5b505afa158015613af3573d6000803e3d6000fd5b505050506040513d6020811015613b0957600080fd5b505191505090565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c80830189905283518084039091018152605c83018085528151918301919091206000909152607c830180855281905260ff8716609c84015260bc830186905260dc8301859052925160019260fc8082019392601f1981019281900390910190855afa158015613bb4573d6000803e3d6000fd5b505050602060405103516001600160a01b0316856001600160a01b031614612afe576040805162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b604482015290519081900360640190fd5b6000806000613c268585614084565b94509050600060fd60f81b6001600160f81b031983161415613cc457613c4c8686614102565b955061ffff16905060fd8110801590613c67575061ffff8111155b613cb8576040805162461bcd60e51b815260206004820152601f60248201527f4e65787455696e7431362c2076616c7565206f7574736964652072616e676500604482015290519081900360640190fd5b92508391506135f59050565b607f60f91b6001600160f81b031983161415613d5457613ce4868661418b565b955063ffffffff16905061ffff81118015613d03575063ffffffff8111155b613cb8576040805162461bcd60e51b815260206004820181905260248201527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604482015290519081900360640190fd5b6001600160f81b03198083161415613dd557613d708686614231565b95506001600160401b0316905063ffffffff8111613cb8576040805162461bcd60e51b815260206004820181905260248201527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604482015290519081900360640190fd5b5060f881901c60fd8110613cb8576040805162461bcd60e51b815260206004820181905260248201527f4e65787456617255696e742c2076616c7565206f7574736964652072616e6765604482015290519081900360640190fd5b60008184841115613ebf5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613e84578181015183820152602001613e6c565b50505050905090810190601f168015613eb15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000828201838110156110ef576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b8051606090613f2f816142d7565b836040516020018083805190602001908083835b60208310613f625780518252601f199092019160209182019101613f43565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310613faa5780518252601f199092019160209182019101613f8b565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052915050919050565b60606001600160ff1b03821115614045576040805162461bcd60e51b815260206004820152601b60248201527f56616c756520657863656564732075696e743235352072616e67650000000000604482015290519081900360640190fd5b60405160208082526000601f5b828210156140745785811a826020860101536001919091019060001901614052565b5050506040818101905292915050565b6000808351836001011115801561409d57508260010183105b6140ee576040805162461bcd60e51b815260206004820181905260248201527f4e657874427974652c204f66667365742065786365656473206d6178696d756d604482015290519081900360640190fd5b505081810160200151600182019250929050565b6000808351836002011115801561411b57508260020183105b6141565760405162461bcd60e51b8152600401808060200182810382526022815260200180614f4b6022913960400191505060405180910390fd5b6000604051846020870101518060011a82538060001a6001830153506002818101604052601d19909101519694019450505050565b600080835183600401111580156141a457508260040183105b6141df5760405162461bcd60e51b8152600401808060200182810382526022815260200180614fb96022913960400191505060405180910390fd5b600060405160046000600182038760208a0101515b838310156142145780821a838601536001830192506001820391506141f4565b505050808201604052602003900351956004949094019450505050565b6000808351836008011115801561424a57508260080183105b6142855760405162461bcd60e51b8152600401808060200182810382526022815260200180614f976022913960400191505060405180910390fd5b600060405160086000600182038760208a0101515b838310156142ba5780821a8386015360018301925060018203915061429a565b505050808201604052602003900351956008949094019450505050565b606060fd826001600160401b031610156142fb576142f48261441d565b90506121a2565b61ffff826001600160401b0316116143d95761431a60fd60f81b614439565b6143238361444d565b6040516020018083805190602001908083835b602083106143555780518252601f199092019160209182019101614336565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061439d5780518252601f19909201916020918201910161437e565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405290506121a2565b63ffffffff826001600160401b031611614403576143fa607f60f91b614439565b61432383614490565b6144146001600160f81b0319614439565b614323836144d3565b604080516001815260f89290921b602083015260218201905290565b60606144478260f81c61441d565b92915050565b6040516002808252606091906000601f5b828210156144805785811a82602086010153600191909101906000190161445e565b5050506022810160405292915050565b6040516004808252606091906000601f5b828210156144c35785811a8260208601015360019190910190600019016144a1565b5050506024810160405292915050565b6040516008808252606091906000601f5b828210156145065785811a8260208601015360019190910190600019016144e4565b5050506028810160405292915050565b60405180610100016040528060608152602001606081526020016060815260200160008152602001600081526020016060815260200160608152602001600081525090565b604051806040016040528060608152602001606081525090565b6040518060200160405280606081525090565b610920806145968339019056fe608060405234801561001057600080fd5b50610900806100206000396000f3fe60806040526004361061007f5760003560e01c80638da5cb5b1161004e5780638da5cb5b1461014a578063c0ee0b8a1461015f578063d1f57894146101f1578063f445b6f31461027e57610086565b806302d05d3f1461008b5780631570f3f8146100bc578063392e53cd146100e85780637c2c671b1461011157610086565b3661008657005b600080fd5b34801561009757600080fd5b506100a0610308565b604080516001600160a01b039092168252519081900360200190f35b3480156100c857600080fd5b506100e6600480360360208110156100df57600080fd5b503561031c565b005b3480156100f457600080fd5b506100fd61041b565b604080519115158252519081900360200190f35b34801561011d57600080fd5b506100e66004803603604081101561013457600080fd5b506001600160a01b038135169060200135610424565b34801561015657600080fd5b506100a06104e3565b34801561016b57600080fd5b506100e66004803603606081101561018257600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156101b257600080fd5b8201836020820111156101c457600080fd5b803590602001918460018302840111640100000000831117156101e657600080fd5b5090925090506104f2565b3480156101fd57600080fd5b506100e66004803603604081101561021457600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561023f57600080fd5b82018360208201111561025157600080fd5b8035906020019184600183028401116401000000008311171561027357600080fd5b5090925090506104f8565b34801561028a57600080fd5b50610293610597565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102cd5781810151838201526020016102b5565b50505050905090810190601f1680156102fa5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60005461010090046001600160a01b031681565b60005461010090046001600160a01b03163314610379576040805162461bcd60e51b815260206004820152601660248201527529b2b73232b91036bab9ba1031329031b932b0ba37b960511b604482015290519081900360640190fd5b600080546040516101009091046001600160a01b03169083908381818185875af1925050503d80600081146103ca576040519150601f19603f3d011682016040523d82523d6000602084013e6103cf565b606091505b5050905080610417576040805162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b5050565b60005460ff1681565b60005461010090046001600160a01b03163314610481576040805162461bcd60e51b815260206004820152601660248201527529b2b73232b91036bab9ba1031329031b932b0ba37b960511b604482015290519081900360640190fd5b600054604080516101009092046001600160a01b031660248301526044808301849052815180840390910181526064909201905260208101805163a9059cbb60e01b6001600160e01b0390911617905282906104de908290610622565b505050565b6001546001600160a01b031681565b50505050565b60005460ff1615610550576040805162461bcd60e51b815260206004820152601c60248201527f436f6e747261637420616c726561647920696e697469616c697a656400000000604482015290519081900360640190fd5b60008054600160ff199091168117610100600160a81b03191661010033021790915580546001600160a01b0319166001600160a01b0385161790556104f26002838361080d565b6002805460408051602060018416156101000260001901909316849004601f8101849004840282018401909252818152929183018282801561061a5780601f106105ef5761010080835404028352916020019161061a565b820191906000526020600020905b8154815290600101906020018083116105fd57829003601f168201915b505050505081565b61062b826107d1565b61067c576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106106ba5780518252601f19909201916020918201910161069b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461071c576040519150601f19603f3d011682016040523d82523d6000602084013e610721565b606091505b509150915081610778576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156104f25780806020019051602081101561079457600080fd5b50516104f25760405162461bcd60e51b815260040180806020018281038252602a8152602001806108a1602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061080557508115155b949350505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061084e5782800160ff1982351617855561087b565b8280016001018555821561087b579182015b8281111561087b578235825591602001919060010190610860565b5061088792915061088b565b5090565b5b80821115610887576000815560010161088c56fe5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122010e645043ba7055fb1ee83b35aafd81099f38b704b7bb09dab330ec96206a4f764736f6c634300060c00335265656e7472616e637947756172643a207265656e7472616e742063616c6c004e65787455696e743235352c206f66667365742065786365656473206d6178696d756d6279746573206c656e67746820646f6573206e6f74206d61746368206164647265737345746843726f7373436861696e4d616e616765722063726f7373436861696e206578656375746564206572726f72214e65787455696e7431362c206f66667365742065786365656473206d6178696d756d5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644e65787455696e7436342c206f66667365742065786365656473206d6178696d756d4e65787455696e7433322c206f66667365742065786365656473206d6178696d756d546f6b656e73207472616e7366657272656420646f6573206e6f74206d617463682074686520657870656374656420616d6f756e744e65787456617242797465732c206f66667365742065786365656473206d6178696d756d46656520616d6f756e742063616e6e6f742062652067726561746572207468616e20616d6f756e74455448207472616e7366657272656420646f6573206e6f74206d617463682074686520657870656374656420616d6f756e74a2646970667358221220cf7112f021f9e2524cc4412d735952b2778a93a00ac3ae2b1657c7f00496535764736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005a51e2ebf8d136926b9ca7b59b60464e7c44d2eb0000000000000000000000000000000000000000000000000000000000000005
-----Decoded View---------------
Arg [0] : _ccmProxyAddress (address): 0x5a51E2ebF8D136926b9cA7b59B60464E7C44d2Eb
Arg [1] : _counterpartChainId (uint64): 5
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000005a51e2ebf8d136926b9ca7b59b60464e7c44d2eb
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000005
Deployed Bytecode Sourcemap
46922:27098:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48052:43;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48052:43:0;-1:-1:-1;;;;;48052:43:0;;:::i;:::-;;;;;;;;;;;;;;;;58480:920;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;58480:920:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;58480:920:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;58480:920:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;58480:920:0;;;;;;;;;;;;-1:-1:-1;58480:920:0;-1:-1:-1;58480:920:0;-1:-1:-1;;;;;58480:920:0;;:::i;:::-;;;;;;;;;;;;;;;;;;59902:996;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;59902:996:0;;;;;;;;;;;;;;;;;:::i;47659:68::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53381:589;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;53381:589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;53381:589:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;53381:589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;53381:589:0;;;;;;;;;;;;-1:-1:-1;53381:589:0;-1:-1:-1;53381:589:0;-1:-1:-1;;;;;53381:589:0;;:::i;51673:551::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;51673:551:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;51673:551:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;51673:551:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;51673:551:0;;;;;;;;;;;;-1:-1:-1;51673:551:0;-1:-1:-1;51673:551:0;-1:-1:-1;;;;;51673:551:0;;:::i;50093:484::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;50093:484:0;;;;;;;;;;;;;;;-1:-1:-1;;;50093:484:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;50093:484:0;;;;;;;;;;;;-1:-1:-1;50093:484:0;-1:-1:-1;50093:484:0;;:::i;:::-;;;;-1:-1:-1;;;;;50093:484:0;;;;;;;;;;;;;;57215:954;;;;;;;;;;;;;;;;-1:-1:-1;;;;;57215:954:0;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;57215:954:0;;;;;;;;;;-1:-1:-1;57215:954:0;;-1:-1:-1;57215:954:0;-1:-1:-1;57215:954:0;:::i;48347:39::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48347:39:0;-1:-1:-1;;;;;48347:39:0;;:::i;55084:1408::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55084:1408:0;;;;;;;;;;-1:-1:-1;55084:1408:0;;-1:-1:-1;55084:1408:0;-1:-1:-1;55084:1408:0;:::i;47864:31::-;;;;;;;;;;;;;:::i;47734:51::-;;;;;;;;;;;;;:::i;47794:24::-;;;;;;;;;;;;;:::i;47825:32::-;;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;47825:32:0;;;;;;;;;;;;;;48260:42;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48260:42:0;-1:-1:-1;;;;;48260:42:0;;:::i;49627:65::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49627:65:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;49627:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;49627:65:0;;;;;;;;;;-1:-1:-1;49627:65:0;;-1:-1:-1;49627:65:0;-1:-1:-1;49627:65:0;:::i;:::-;;52433:555;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;52433:555:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;52433:555:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;52433:555:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;52433:555:0;;;;;;;;;;;;-1:-1:-1;52433:555:0;-1:-1:-1;52433:555:0;-1:-1:-1;;;;;52433:555:0;;:::i;50891:588::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;50891:588:0;;;;;;;;;;;;;;;-1:-1:-1;;;50891:588:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;50891:588:0;;;;;;;;;;-1:-1:-1;50891:588:0;;-1:-1:-1;50891:588:0;-1:-1:-1;50891:588:0;:::i;48166:44::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;48166:44:0;;:::i;48052:43::-;;;;;;;;;;;;;:::o;58480:920::-;58696:4;49162:8;;;;;;;;;-1:-1:-1;;;;;49162:8:0;-1:-1:-1;;;;;49162:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49162:34:0;-1:-1:-1;;;;;49148:48:0;:10;:48;49126:119;;;;;-1:-1:-1;;;49126:119:0;;;;;;;;;;;;-1:-1:-1;;;49126:119:0;;;;;;;;;;;;;;;21717:11:::1;::::0;::::1;;21709:55;;;::::0;;-1:-1:-1;;;21709:55:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;21709:55:0;;;;;;;;;;;;;::::1;;21856:5;21842:19:::0;;-1:-1:-1;;21842:19:0::1;::::0;;;;-1:-1:-1;;;;;58726:34:0;;::::2;-1:-1:-1::0;;;58742:18:0;;::::2;;58726:34;58718:63;;;::::0;;-1:-1:-1;;;58718:63:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;58718:63:0;;;;;;;;;;;;;::::2;;58794:26;;:::i;:::-;58823:35;58850:7;;58823:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;58823:26:0::2;::::0;-1:-1:-1;;;58823:35:0:i:2;:::-;58877:18:::0;;:25;58794:64;;-1:-1:-1;58869:63:0::2;;;::::0;;-1:-1:-1;;;58869:63:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;58869:63:0;;;;;;;;;;;;;::::2;;58951:4;:16;;;:23;58978:2;58951:29;58943:61;;;::::0;;-1:-1:-1;;;58943:61:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;58943:61:0;;;;;;;;;;;;;::::2;;59017:19;59039:38;59060:4;:16;;;59039:20;:38::i;:::-;59017:60;;59088:17;59108:36;59129:4;:14;;;59108:20;:36::i;:::-;59088:56;;59157:78;59184:11;59197:17;;59157:78;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;;59216:18:0;;;-1:-1:-1;59157:26:0::2;::::0;-1:-1:-1;59157:78:0:i:2;:::-;59246:49;59259:9;59270:11;59283:4;:11;;;59246:12;:49::i;:::-;59313:57;59325:11;59338:9;59349:4;:11;;;59362:7;;59313:57;;;;-1:-1:-1::0;;;;;59313:57:0::2;;;;;;-1:-1:-1::0;;;;;59313:57:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;;::::2;-1:-1:-1::0;;59313:57:0::2;::::0;;::::2;::::0;;::::2;::::0;-1:-1:-1;59313:57:0;;-1:-1:-1;;;;;;;59313:57:0::2;59388:4;59381:11;;;;;22022::::1;:18:::0;;-1:-1:-1;;22022:18:0::1;22036:4;22022:18;::::0;;58480:920;;-1:-1:-1;;;;;58480:920:0:o;59902:996::-;60118:10;60063:4;60107:22;;;:10;:22;;;;;;;;:30;;:22;:30;60085:97;;;;;-1:-1:-1;;;60085:97:0;;;;;;;;;;;;-1:-1:-1;;;60085:97:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;60199:28:0;;60195:412;;60477:42;;60458:12;;-1:-1:-1;;;;;60477:22:0;;;60507:7;;60458:12;60477:42;60458:12;60477:42;60507:7;60477:22;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60457:62;;;60542:7;60534:35;;;;;-1:-1:-1;;;60534:35:0;;;;;;;;;;;;-1:-1:-1;;;60534:35:0;;;;;;;;;;;;;;;60591:4;60584:11;;;;;60195:412;60715:140;;;-1:-1:-1;;;;;60715:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;60715:140:0;-1:-1:-1;;;60715:140:0;;;60639:10;;60661:205;;60639:10;;60661:19;:205::i;:::-;60886:4;60879:11;;;59902:996;;;;;;:::o;47659:68::-;;;;;;;;;;;;;;;;;;;:::o;53381:589::-;53604:4;49162:8;;;;;;;;;-1:-1:-1;;;;;49162:8:0;-1:-1:-1;;;;;49162:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49162:34:0;-1:-1:-1;;;;;49148:48:0;:10;:48;49126:119;;;;;-1:-1:-1;;;49126:119:0;;;;;;;;;;;;-1:-1:-1;;;49126:119:0;;;;;;;;;;;;;;;21717:11:::1;::::0;::::1;;21709:55;;;::::0;;-1:-1:-1;;;21709:55:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;21709:55:0;;;;;;;;;;;;;::::1;;21856:5;21842:19:::0;;-1:-1:-1;;21842:19:0::1;::::0;;;;-1:-1:-1;;;;;53634:34:0;;::::2;-1:-1:-1::0;;;53650:18:0;;::::2;;53634:34;53626:63;;;::::0;;-1:-1:-1;;;53626:63:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;53626:63:0;;;;;;;;;;;;;::::2;;53702:31;;:::i;:::-;53736:40;53768:7;;53736:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;53736:31:0::2;::::0;-1:-1:-1;;;53736:40:0:i:2;:::-;53702:74;;53787:151;53824:42;53845:4;:20;;;53824;:42::i;:::-;53881:17;;53787:151;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;;53913:14:0;;;-1:-1:-1;53787:22:0::2;::::0;-1:-1:-1;53787:151:0:i:2;:::-;53958:4;53951:11;;;22022::::1;:18:::0;;-1:-1:-1;;22022:18:0::1;22036:4;22022:18;::::0;;53381:589;;-1:-1:-1;;;;;53381:589:0:o;51673:551::-;51901:4;49162:8;;;;;;;;;-1:-1:-1;;;;;49162:8:0;-1:-1:-1;;;;;49162:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49162:34:0;-1:-1:-1;;;;;49148:48:0;:10;:48;49126:119;;;;;-1:-1:-1;;;49126:119:0;;;;;;;;;;;;-1:-1:-1;;;49126:119:0;;;;;;;;;;;;;;;21717:11:::1;::::0;::::1;;21709:55;;;::::0;;-1:-1:-1;;;21709:55:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;21709:55:0;;;;;;;;;;;;;::::1;;21856:5;21842:19:::0;;-1:-1:-1;;21842:19:0::1;::::0;;;;-1:-1:-1;;;;;51931:34:0;;::::2;-1:-1:-1::0;;;51947:18:0;;::::2;;51931:34;51923:63;;;::::0;;-1:-1:-1;;;51923:63:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;51923:63:0;;;;;;;;;;;;;::::2;;51999:27;;:::i;:::-;52029:36;52057:7;;52029:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;52029:27:0::2;::::0;-1:-1:-1;;;52029:36:0:i:2;:::-;51999:66;;52076:24;52103:43;52124:4;:21;;;52103:20;:43::i;:::-;-1:-1:-1::0;;;;;52157:28:0::2;;::::0;;;:10:::2;:28;::::0;;;;:35;;52188:4:::2;-1:-1:-1::0;;52157:35:0;;::::2;::::0;::::2;::::0;;;22022:18;;::::1;::::0;::::1;::::0;;;52188:4;51673:551;-1:-1:-1;;;;;;;;51673:551:0:o;50093:484::-;50278:7;50303:12;50318:74;50341:13;50369:12;;50318:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;50318:8:0;;-1:-1:-1;;;50318:74:0:i;:::-;50444:66;;;-1:-1:-1;;;;;;50444:66:0;;;;;;;;50483:4;50444:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50420:101;;;;;;;;-1:-1:-1;;;;;50541:28:0;;50093:484;-1:-1:-1;;;;;50093:484:0:o;57215:954::-;57530:4;21717:11;;;;21709:55;;;;;-1:-1:-1;;;21709:55:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;21709:55:0;;;;;;;;;;;;;;;21856:5;21842:19;;-1:-1:-1;;21842:19:0;;;57877:47:::1;::::0;57889:10;;57901:7;;;;:10;::::1;;;;;;;;;;57913:7;;57921:1;57913:10;;;;;;;;;;;;;57877:11;:47::i;:::-;57937:200;57957:10;57982:16;;57937:200;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;;57937:200:0::1;::::0;;::::1;;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;;;;-1:-1:-1;58013:12:0;;-1:-1:-1;58013:12:0;;;;57937:200;::::1;58013:12:::0;;;;57937:200;::::1;;;;;;;;;;;;;;;;;;;;;;;;;58040:10;;57937:200;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;-1:-1:-1;58065:7:0;;-1:-1:-1;58065:7:0;;-1:-1:-1;57937:200:0;-1:-1:-1;58065:10:0;::::1;;;;;;;;;;58090:7;;58098:1;58090:10;;;;;;;;;;;;;58115:11;;57937:200;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;57937:5:0::1;::::0;-1:-1:-1;;;57937:200:0:i:1;:::-;-1:-1:-1::0;58157:4:0::1;22022:11:::0;:18;;-1:-1:-1;;22022:18:0;22036:4;22022:18;;;57215:954;;-1:-1:-1;;;;;;;;;;;57215:954:0:o;48347:39::-;;;;;;;;;;;;;;;:::o;55084:1408::-;55449:4;21717:11;;;;21709:55;;;;;-1:-1:-1;;;21709:55:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;21709:55:0;;;;;;;;;;;;;;;21856:5;21842:19;;-1:-1:-1;;21842:19:0;;;-1:-1:-1;;;;;55479:23:0;::::1;::::0;;:7:::1;:23;::::0;;;;;21842:19;55479:23:::1;55471:58;;;::::0;;-1:-1:-1;;;55471:58:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;55471:58:0;;;;;;;;;;;;;::::1;;55542:13;55565:14;55542:38;;55591:229;55629:6;-1:-1:-1::0;;;;;55629:12:0::1;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;55658:10;55683:16;;55591:229;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55714:12;;55591:229;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55741:11;;55591:229;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55767:7;;55591:229;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55789:2;55806:3;;55591:229;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;55591:23:0::1;::::0;-1:-1:-1;;;55591:229:0:i:1;:::-;56164:73;56186:14;56202:10;56214:7;;56222:1;56214:10;;;;;;;;;;;;;56226:7;;56234:1;56226:10;;;;;;;;;;;;;56164:21;:73::i;:::-;56250:210;56270:10;56295:16;;56250:210;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56326:12;;56250:210;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;-1:-1:-1;56353:20:0::1;::::0;;-1:-1:-1;;;56353:20:0;;;;-1:-1:-1;;;;;56353:18:0;::::1;::::0;-1:-1:-1;56353:18:0::1;::::0;-1:-1:-1;56353:20:0::1;::::0;;::::1;::::0;-1:-1:-1;56353:20:0;;;;;;;:18;:20;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;56353:20:0::1;::::0;::::1;;::::0;::::1;::::0;::::1;;;;;::::0;::::1;;;;;;;;;;;;;;;-1:-1:-1::0;;;56353:20:0::1;;;;;;::::0;::::1;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;;;;;::::0;::::1;;::::0;;-1:-1:-1;;;56353:20:0;::::1;::::0;;::::1;::::0;-1:-1:-1;56353:20:0::1;;;;;::::0;::::1;;::::0;;-1:-1:-1;56353:20:0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;::::1;;;;;;;;::::0;;::::1;::::0;;;::::1;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;56388:7;;56396:1;56388:10;;;;;;;;;;;;;56413:7;;56421:1;56413:10;;;;;;;;;;;;;56438:11;;56250:210;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;56250:5:0::1;::::0;-1:-1:-1;;;56250:210:0:i:1;:::-;56480:4;56473:11;;;22022::::0;:18;;-1:-1:-1;;22022:18:0;22036:4;22022:18;;;55084:1408;;-1:-1:-1;;;;;;;;;;;;;55084:1408:0:o;47864:31::-;;;;:::o;47734:51::-;47783:1;47734:51;:::o;47794:24::-;;;;;;-1:-1:-1;;;;;47794:24:0;;:::o;47825:32::-;;;-1:-1:-1;;;47825:32:0;;-1:-1:-1;;;;;47825:32:0;;:::o;48260:42::-;;;;;;;;;;;;;;;:::o;49627:65::-;;;;;:::o;52433:555::-;52664:4;49162:8;;;;;;;;;-1:-1:-1;;;;;49162:8:0;-1:-1:-1;;;;;49162:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49162:34:0;-1:-1:-1;;;;;49148:48:0;:10;:48;49126:119;;;;;-1:-1:-1;;;49126:119:0;;;;;;;;;;;;-1:-1:-1;;;49126:119:0;;;;;;;;;;;;;;;21717:11:::1;::::0;::::1;;21709:55;;;::::0;;-1:-1:-1;;;21709:55:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;;;;;;;21709:55:0;;;;;;;;;;;;;::::1;;21856:5;21842:19:::0;;-1:-1:-1;;21842:19:0::1;::::0;;;;-1:-1:-1;;;;;52694:34:0;;::::2;-1:-1:-1::0;;;52710:18:0;;::::2;;52694:34;52686:63;;;::::0;;-1:-1:-1;;;52686:63:0;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;52686:63:0;;;;;;;;;;;;;::::2;;52762:27;;:::i;:::-;52792:36;52820:7;;52792:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;::::0;;;;-1:-1:-1;52792:27:0::2;::::0;-1:-1:-1;;;52792:36:0:i:2;:::-;52762:66;;52839:24;52866:43;52887:4;:21;;;52866:20;:43::i;:::-;-1:-1:-1::0;;;;;52920:28:0::2;52951:5;52920:28:::0;;;:10:::2;:28;::::0;;;;:36;;-1:-1:-1;;52920:36:0::2;::::0;;-1:-1:-1;52920:36:0;;-1:-1:-1;;22022:11:0::1;:18:::0;;-1:-1:-1;;22022:18:0::1;22036:4;22022:18;::::0;;52433:555;;-1:-1:-1;;;;;52433:555:0:o;50891:588::-;51048:4;21717:11;;;;21709:55;;;;;-1:-1:-1;;;21709:55:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;21709:55:0;;;;;;;;;;;;;;;21856:5;21842:19;;-1:-1:-1;;21842:19:0;;;-1:-1:-1;;;;;51078:27:0;::::1;51070:58;;;::::0;;-1:-1:-1;;;51070:58:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;51070:58:0;;;;;;;;;;;;;::::1;;51147:24:::0;51139:54:::1;;;::::0;;-1:-1:-1;;;51139:54:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;51139:54:0;;;;;;;;;;;;;::::1;;51206:12;51221:74;51244:13;51272:12;;51221:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;51221:8:0::1;::::0;-1:-1:-1;;;51221:74:0:i:1;:::-;51206:89;;51308:13;51341:4;51324:24;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;51308:40;;51359:6;-1:-1:-1::0;;;;;51359:17:0::1;;51377:13;51392:12;;51359:46;;;;;;;;;;;;;-1:-1:-1::0;;;;;51359:46:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;;;;;;;;51416:24:0::1;;::::0;;;:7:::1;:24;::::0;;;;:31;;51443:4:::1;-1:-1:-1::0;;51416:31:0;;::::1;::::0;::::1;::::0;;;22022:18;;;;;;;;51443:4;50891:588;-1:-1:-1;;;;;50891:588:0:o;48166:44::-;;;;;;;;;;;;;;;:::o;69540:502::-;69620:21;;:::i;:::-;69654:26;;:::i;:::-;69691:11;69745:41;69773:7;69782:3;69745:27;:41::i;:::-;69717:69;;;;-1:-1:-1;69823:41:0;69851:7;69717:69;69823:27;:41::i;:::-;69798:16;;;69797:67;;;;;-1:-1:-1;69899:41:0;69927:7;69797:67;69899:27;:41::i;:::-;69876:14;;;69875:65;;;;;-1:-1:-1;69972:40:0;69999:7;69875:65;69972:26;:40::i;:::-;-1:-1:-1;69952:11:0;;;69951:61;-1:-1:-1;69952:4:0;-1:-1:-1;69540:502:0;;;;:::o;24337:447::-;24402:12;24440:3;:10;24454:2;24440:16;24432:64;;;;-1:-1:-1;;;24432:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24758:4:0;24749:14;24743:21;;24516:259::o;62059:452::-;62259:13;:20;62283:2;62259:26;62251:59;;;;;-1:-1:-1;;;62251:59:0;;;;;;;;;;;;-1:-1:-1;;;62251:59:0;;;;;;;;;;;;;;;62321:13;62378;62406:12;62347:82;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;62347:82:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;62347:82:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62347:82:0;;;;;;;;;;;;;-1:-1:-1;;62347:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62337:93;;;;;;62321:109;;62473:5;62449:8;:20;62458:10;-1:-1:-1;;;;;62449:20:0;-1:-1:-1;;;;;62449:20:0;;;;;;;;;;;;;:29;62441:62;;;;;-1:-1:-1;;;62441:62:0;;;;;;;;;;;;-1:-1:-1;;;62441:62:0;;;;;;;;;;;;;;67517:807;-1:-1:-1;;;;;67667:28:0;;67663:400;;67945:35;;67926:12;;-1:-1:-1;;;;;67945:15:0;;;67968:7;;67926:12;67945:35;67926:12;67945:35;67968:7;67945:15;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67925:55;;;68003:7;67995:35;;;;;-1:-1:-1;;;67995:35:0;;;;;;;;;;;;-1:-1:-1;;;67995:35:0;;;;;;;;;;;;;;;68045:7;;;67663:400;68171:134;;;-1:-1:-1;;;;;68171:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;68171:134:0;-1:-1:-1;;;68171:134:0;;;68095:10;;68117:199;;68095:10;;68117:19;:199::i;67517:807::-;;;;:::o;71688:1114::-;72292:27;72312:5;72292:11;:27::i;:::-;72284:71;;;;;-1:-1:-1;;;72284:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;72429:12;72443:23;72478:5;-1:-1:-1;;;;;72470:19:0;72490:4;72470:25;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;72470:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72428:67;;;;72514:7;72506:52;;;;;-1:-1:-1;;;72506:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72575:17;;:21;72571:224;;72717:10;72706:30;;;;;;;;;;;;;;;-1:-1:-1;72706:30:0;72698:85;;;;-1:-1:-1;;;72698:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70050:369;70135:26;;:::i;:::-;70174:31;;:::i;:::-;70216:11;70266:41;70294:7;70303:3;70266:27;:41::i;:::-;70242:65;;;;-1:-1:-1;70348:41:0;70376:7;70242:65;70348:27;:41::i;:::-;-1:-1:-1;70319:20:0;;;70318:71;-1:-1:-1;70319:20:0;70050:369;-1:-1:-1;;70050:369:0:o;61237:523::-;61419:13;:20;61443:2;61419:26;61411:59;;;;;-1:-1:-1;;;61411:59:0;;;;;;;;;;;;-1:-1:-1;;;61411:59:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;61503:20:0;;61535:1;61503:20;;;:8;:20;;;;;;:34;61481:108;;;;;-1:-1:-1;;;61481:108:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;61602:13;61659;61687:12;61628:82;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;61628:82:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;61628:82:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;61628:82:0;;;;;;;;;;;;;-1:-1:-1;;61628:82:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;61628:82:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;61628:82:0;;;;;61618:93;;;;;;;;;-1:-1:-1;;;;;61724:20:0;;;;-1:-1:-1;61724:20:0;;;:8;:20;;;;;;;:28;;;;-1:-1:-1;;;;;;;61237:523:0:o;70427:282::-;70508:22;;:::i;:::-;70543:27;;:::i;:::-;70581:11;70638:41;70666:7;70675:3;70638:27;:41::i;:::-;-1:-1:-1;70607:72:0;;-1:-1:-1;70607:72:0;70427:282;-1:-1:-1;;70427:282:0:o;70994:301::-;71136:7;71209:11;;;;;;;;;;;;;;;;;71235:13;71263:12;71178:108;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;71178:108:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;71178:108:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;71178:108:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71168:119;;;;;;71161:126;;70994:301;;;;:::o;66598:844::-;-1:-1:-1;;;;;66748:28:0;;66744:165;;66814:7;66801:9;:20;66793:83;;;;-1:-1:-1;;;66793:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66891:7;;66744:165;66980:30;;;-1:-1:-1;;;66980:30:0;;67004:4;66980:30;;;;;;66941:10;;66921:11;;-1:-1:-1;;;;;66980:15:0;;;;;:30;;;;;;;;;;;;;;:15;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;66980:30:0;67075:174;;;67162:10;67075:174;;;;67199:4;67075:174;;;;;;;;;;;;;;;;;;;;;;;;;;;;66980:30;67075:174;;;;-1:-1:-1;;;;;67075:174:0;-1:-1:-1;;;67075:174:0;;;66980:30;;-1:-1:-1;67021:239:0;;67055:5;;67021:19;:239::i;:::-;67271:19;67293:42;67328:6;67293:5;-1:-1:-1;;;;;67293:15:0;;67317:4;67293:30;;;;;;;;;;;;;-1:-1:-1;;;;;67293:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67293:30:0;;:34;:42::i;:::-;67271:64;;67369:7;67354:11;:22;67346:88;;;;-1:-1:-1;;;67346:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66598:844;;;;;;:::o;62593:1514::-;62889:16;:23;62916:2;62889:29;62881:65;;;;;-1:-1:-1;;;62881:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;62987:1;62965:12;:19;:23;62957:53;;;;;-1:-1:-1;;;62957:53:0;;;;;;;;;;;;-1:-1:-1;;;62957:53:0;;;;;;;;;;;;;;;63049:1;63029:10;:17;:21;63021:49;;;;;-1:-1:-1;;;63021:49:0;;;;;;;;;;;;-1:-1:-1;;;63021:49:0;;;;;;;;;;;;;;;63099:1;63089:7;:11;63081:53;;;;;-1:-1:-1;;;63081:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;63166:7;63153:10;:20;63145:73;;;;-1:-1:-1;;;63145:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63231:74;63258:14;63274:16;63292:12;63231:26;:74::i;:::-;63318:28;;:::i;:::-;63349:366;;;;;;;;63394:36;63415:14;63394:20;:36::i;:::-;63349:366;;;;63458:12;63349:366;;;;63496:10;63349:366;;;;63529:7;63349:366;;;;63562:10;63349:366;;;;63599:11;63349:366;;;;63655:10;63638:28;;;;;;-1:-1:-1;;;;;63638:28:0;;;;;;;;;;;;;;;;;;;;;;63349:366;;;;63688:15;:13;:15::i;:::-;63349:366;;63318:397;-1:-1:-1;63728:19:0;63750:32;63318:397;63750:24;:32::i;:::-;63728:54;;63793:7;63803:9;:7;:9::i;:::-;63793:19;;63845:3;-1:-1:-1;;;;;63845:14:0;;63860:18;;;;;;;;;-1:-1:-1;;;;;63860:18:0;63880:16;63908:6;63845:70;;;;;;;;;;;;;-1:-1:-1;;;;;63845:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;63845:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63845:70:0;63823:167;;;;-1:-1:-1;;;63823:167:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64008:91;64018:14;64034:10;64046:18;;;;;;;;;-1:-1:-1;;;;;64046:18:0;64066:12;64080:10;64092:6;64008:91;;;;-1:-1:-1;;;;;64008:91:0;;;;;;-1:-1:-1;;;;;64008:91:0;;;;;;-1:-1:-1;;;;;64008:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64008:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64008:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62593:1514;;;;;;;;;;:::o;64171:791::-;64500:15;64586:10;64611:16;64642:12;64669:11;64695:7;64703:1;64695:10;;;;;;;;;;;;;;64720:7;64728:1;64720:10;;;;;;;;;;;;;;64745:7;64753:1;64745:10;;;;;;;;;;;;;;64528:238;;;;;;-1:-1:-1;;;64528:238:0;;;;;;-1:-1:-1;;;;;64528:238:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;64528:238:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;64528:238:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64528:238:0;;;;;;;;;;;;;-1:-1:-1;;64528:238:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;64528:238:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64528:238:0;;;;;;;;;;;;;-1:-1:-1;;64528:238:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;64528:238:0;;;;;;;;;;;;;;;;-1:-1:-1;64528:238:0;;;;;;;-1:-1:-1;64528:238:0;;;;;;;;;;;;;;;;;;;;;;;64518:249;;;;;;;;;-1:-1:-1;64788:21:0;;;:12;:21;;;;;;;64518:249;;-1:-1:-1;64788:21:0;;:30;;-1:-1:-1;64780:63:0;;-1:-1:-1;;;64780:63:0;;;;-1:-1:-1;;;64780:63:0;;;;;;;;;;;;-1:-1:-1;;;64780:63:0;;;;;;;;;;;;;;;64854:21;;;;:12;:21;;;;;:28;;-1:-1:-1;;64854:28:0;64878:4;64854:28;;;64939:6;;64893:61;;64867:7;;64921:12;;64935:2;;64939:3;;64854:21;64939:6;;;;;;;;;;64947:3;64951:1;64947:6;;;;;;;;;;;;;;64893:18;:61::i;:::-;64171:791;;;;;;;;;:::o;65251:939::-;65471:14;-1:-1:-1;;;;;65501:28:0;;65497:345;;65546:14;65563:21;65546:38;;65601:6;-1:-1:-1;;;;;65601:23:0;;65625:11;65601:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65654:19;65676:33;65702:6;65676:21;:25;;:33;;;;:::i;:::-;65654:55;;65747:7;65732:11;:22;65724:85;;;;-1:-1:-1;;;65724:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65824:7;;;;;65497:345;65913:30;;;-1:-1:-1;;;65913:30:0;;65937:4;65913:30;;;;;;65874:10;;65854:11;;-1:-1:-1;;;;;65913:15:0;;;;;:30;;;;;;;;;;;;;;:15;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;65913:30:0;65956:50;;;-1:-1:-1;;;65956:50:0;;-1:-1:-1;;;;;65956:50:0;;;;;;;;;;;;;;;65913:30;;-1:-1:-1;65956:25:0;;;;;;:50;;;;;-1:-1:-1;;65956:50:0;;;;;;;;-1:-1:-1;65956:25:0;:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66019:19;66041:42;66076:6;66041:5;-1:-1:-1;;;;;66041:15:0;;66065:4;66041:30;;;;;;;;;;;;;-1:-1:-1;;;;;66041:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;:42;66019:64;;66117:7;66102:11;:22;66094:88;;;;-1:-1:-1;;;66094:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65251:939;;;;;;;;:::o;8204:2656::-;8283:12;8297:7;8317:8;8352:25;8364:4;8370:6;8352:11;:25::i;:::-;8412:11;;8336:41;;-1:-1:-1;8336:41:0;;-1:-1:-1;8396:12:0;;;:27;;;;:52;;;8445:3;8436:6;:12;8427:6;:21;8396:52;8388:101;;;;-1:-1:-1;;;8388:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8500:22;8563:11;;8588:1991;;;;10723:4;10717:11;10704:24;;10776:4;10765:9;10761:20;10755:4;10748:34;8556:2241;;8588:1991;8773:4;8767:11;8754:24;;9438:2;9433:3;9429:12;9826:9;9819:17;9813:4;9809:28;9797:9;9786;9782:25;9778:60;9875:3;9871:2;9867:12;10126:6;10112:9;10105:17;10099:4;10095:28;10083:9;10077:4;10073:20;10069:55;10065:68;9899:432;10160:3;10156:2;10153:11;9899:432;;;10302:9;;10291:21;;10202:4;10194:13;;;;10235;9899:432;;;-1:-1:-1;;10351:22:0;;;10559:2;10542:11;-1:-1:-1;;10538:25:0;10532:4;10525:39;-1:-1:-1;8556:2241:0;-1:-1:-1;10828:9:0;-1:-1:-1;10839:12:0;;;-1:-1:-1;8204:2656:0;;;;;;:::o;6859:975::-;6938:7;6947;6990:4;:11;6975:6;6984:2;6975:11;:26;;:50;;;;;7014:6;7023:2;7014:11;7005:6;:20;6975:50;6967:98;;;;-1:-1:-1;;;6967:98:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7076:9;7142:4;7136:11;7176:4;7231;7280;7271:7;7267:18;7344:6;7337:4;7331;7327:15;7323:28;7317:35;7194:386;7379:7;7371:6;7368:19;7194:386;;;7557:6;7549;7544:20;7535:6;7525:8;7521:21;7513:52;7429:4;7421:6;7417:17;7407:27;;7474:4;7466:6;7462:17;7452:27;;7194:386;;;-1:-1:-1;;;7607:22:0;;7601:4;7594:36;7649:15;;-1:-1:-1;;;;;;7693:71:0;;;7685:107;;;;;-1:-1:-1;;;7685:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;7811:1;7823:2;7814:11;;;;;-1:-1:-1;;;6859:975:0:o;73398:619::-;73458:4;73926:20;;73769:66;73966:23;;;;;;:42;;-1:-1:-1;73993:15:0;;;73966:42;73958:51;73398:619;-1:-1:-1;;;;73398:619:0:o;37157:136::-;37215:7;37242:43;37246:1;37249;37242:43;;;;;;;;;;;;;;;;;:3;:43::i;24946:690::-;25200:4;25194:11;;25332:4;25321:16;;25008:15;25469:14;;;;25462:4;25454:13;;25447:37;25605:13;;;25592:27;;25194:11;25044:585::o;70856:130::-;70898:7;70931:19;70948:1;70931:12;;:16;;:19;;;;:::i;:::-;70916:12;:34;;;;-1:-1:-1;70856:130:0;:::o;68876:656::-;68960:12;68985:17;69051:46;69078:4;:18;;;69051:26;:46::i;:::-;69112:44;69139:4;:16;;;69112:26;:44::i;:::-;69171:42;69198:4;:14;;;69171:26;:42::i;:::-;69228:38;69254:4;:11;;;69228:25;:38::i;:::-;69281:41;69307:4;:14;;;69281:25;:41::i;:::-;69337:43;69364:4;:15;;;69337:26;:43::i;:::-;69395:44;69422:4;:16;;;69395:26;:44::i;:::-;69454:37;69480:4;:10;;;69454:25;:37::i;:::-;69020:482;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69020:482:0;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69020:482:0;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69020:482:0;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69020:482:0;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69020:482:0;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69020:482:0;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;69020:482:0;;;;;;;;;;;;;-1:-1:-1;;69020:482:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69013:489;;69520:4;69513:11;;;68876:656;;;:::o;70717:131::-;70758:3;70772:7;70786:8;;;;;;;;;-1:-1:-1;;;;;70786:8:0;-1:-1:-1;;;;;70786:32:0;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;70786:34:0;;-1:-1:-1;;70717:131:0;:::o;68403:465::-;68633:99;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68623:110;;;;;;;;;68597:23;68777:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68633:99;-1:-1:-1;;68777:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;68768:47:0;:5;-1:-1:-1;;;;;68768:47:0;;68746:114;;;;;-1:-1:-1;;;68746:114:0;;;;;;;;;;;;-1:-1:-1;;;68746:114:0;;;;;;;;;;;;;;12132:1186;12210:4;12216:7;12236:6;12267:22;12276:4;12282:6;12267:8;:22::i;:::-;12253:36;-1:-1:-1;12253:36:0;-1:-1:-1;12302:10:0;-1:-1:-1;;;;;;;;;12327:9:0;;;12323:988;;;12420:24;12431:4;12437:6;12420:10;:24::i;:::-;12402:42;-1:-1:-1;12402:42:0;;;-1:-1:-1;12476:4:0;12467:13;;;;;:32;;;12493:6;12484:5;:15;;12467:32;12459:76;;;;;-1:-1:-1;;;12459:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;12558:5;-1:-1:-1;12565:6:0;;-1:-1:-1;12550:22:0;;-1:-1:-1;12550:22:0;12323:988;-1:-1:-1;;;;;;;;;12594:9:0;;;12590:721;;;12687:24;12698:4;12704:6;12687:10;:24::i;:::-;12669:42;-1:-1:-1;12669:42:0;;;-1:-1:-1;12742:6:0;12734:14;;:37;;;;;12761:10;12752:5;:19;;12734:37;12726:82;;;;;-1:-1:-1;;;12726:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;12590:721;-1:-1:-1;;;;;;12867:9:0;;;;12863:448;;;12960:24;12971:4;12977:6;12960:10;:24::i;:::-;12942:42;-1:-1:-1;;;;;;12942:42:0;;-1:-1:-1;13015:10:0;13007:18;;12999:63;;;;;-1:-1:-1;;;12999:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;12863:448;-1:-1:-1;13182:8:0;;;;13221:4;13213:12;;13205:57;;;;;-1:-1:-1;;;13205:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;37588:192;37674:7;37710:12;37702:6;;;;37694:29;;;;-1:-1:-1;;;37694:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;37746:5:0;;;37588:192::o;36701:181::-;36759:7;36791:5;;;36815:6;;;;36807:46;;;;;-1:-1:-1;;;36807:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;19172:185;19280:11;;19237:12;;19327:15;19280:11;19327:12;:15::i;:::-;19344:4;19310:39;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;19310:39:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;19310:39:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19310:39:0;;;;;;;;;;;;;-1:-1:-1;;19310:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19303:46;;;19172:185;;;:::o;18257:747::-;18313:12;-1:-1:-1;;;;;18346:1:0;:71;;18338:111;;;;;-1:-1:-1;;;18338:111:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;18527:4;18521:11;18561:4;18579:21;;;18651:4;18687;18614:307;18718:7;18710:6;18707:19;18614:307;;;18903:1;18895:6;18890:15;18881:6;18874:4;18868;18864:15;18860:28;18852:54;18768:4;18756:17;;;;;-1:-1:-1;;18801:17:0;18614:307;;;-1:-1:-1;;;18958:4:0;18948:15;;;18935:29;;18948:15;18257:747;-1:-1:-1;;18257:747:0:o;2064:337::-;2140:4;2146:7;2188:4;:11;2174:6;2183:1;2174:10;:25;;:48;;;;;2212:6;2221:1;2212:10;2203:6;:19;2174:48;2166:93;;;;;-1:-1:-1;;;2166:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2321:28:0;;;2335:4;2321:28;2315:35;2391:1;2382:10;;2064:337;;;;;:::o;3516:600::-;3594:6;3602:7;3644:4;:11;3630:6;3639:1;3630:10;:25;;:48;;;;;3668:6;3677:1;3668:10;3659:6;:19;3630:48;3622:95;;;;-1:-1:-1;;;3622:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3730:8;3795:4;3789:11;3855:6;3848:4;3842;3838:15;3834:28;3828:35;3906:6;3900:4;3895:18;3885:8;3877:37;3965:6;3962:1;3957:15;3950:4;3940:8;3936:19;3928:45;-1:-1:-1;4014:4:0;4000:19;;;3994:4;3987:33;-1:-1:-1;;4045:19:0;;;4039:26;;4097:10;;;-1:-1:-1;;;;3516:600:0:o;4416:875::-;4494:6;4502:7;4544:4;:11;4530:6;4539:1;4530:10;:25;;:48;;;;;4568:6;4577:1;4568:10;4559:6;:19;4530:48;4522:95;;;;-1:-1:-1;;;4522:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4628:8;4693:4;4687:11;4727:4;4782;4831;4822:7;4818:18;4895:6;4888:4;4882;4878:15;4874:28;4868:35;4745:386;4930:7;4922:6;4919:19;4745:386;;;5108:6;5100;5095:20;5086:6;5076:8;5072:21;5064:52;4980:4;4972:6;4968:17;4958:27;;5025:4;5017:6;5013:17;5003:27;;4745:386;;;-1:-1:-1;;;5158:22:0;;;5152:4;5145:36;5224:4;5220:18;5206:33;;5200:40;;5281:1;5272:10;;;;;-1:-1:-1;;;;4416:875:0:o;5590:::-;5668:6;5676:7;5718:4;:11;5704:6;5713:1;5704:10;:25;;:48;;;;;5742:6;5751:1;5742:10;5733:6;:19;5704:48;5696:95;;;;-1:-1:-1;;;5696:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5802:8;5867:4;5861:11;5901:4;5956;6005;5996:7;5992:18;6069:6;6062:4;6056;6052:15;6048:28;6042:35;5919:386;6104:7;6096:6;6093:19;5919:386;;;6282:6;6274;6269:20;6260:6;6250:8;6246:21;6238:52;6154:4;6146:6;6142:17;6132:27;;6199:4;6191:6;6187:17;6177:27;;5919:386;;;-1:-1:-1;;;6332:22:0;;;6326:4;6319:36;6398:4;6394:18;6380:33;;6374:40;;6455:1;6446:10;;;;;-1:-1:-1;;;;5590:875:0:o;19365:453::-;19420:12;19453:4;19449:1;-1:-1:-1;;;;;19449:8:0;;19445:366;;;19474:20;19491:1;19474:10;:20::i;:::-;19467:27;;;;19445:366;19518:6;19513:1;-1:-1:-1;;;;;19513:11:0;;19509:302;;19559:15;-1:-1:-1;;;19559:9:0;:15::i;:::-;19576:22;19595:1;19576:11;:22::i;:::-;19542:57;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;19542:57:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;19542:57:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19542:57:0;;;;;;;;;;;;;-1:-1:-1;;19542:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19535:64;;;;19509:302;19623:10;19618:1;-1:-1:-1;;;;;19618:15:0;;19614:197;;19674:15;-1:-1:-1;;;19674:9:0;:15::i;:::-;19691:22;19710:1;19691:11;:22::i;19614:197::-;19762:15;-1:-1:-1;;;;;;19762:9:0;:15::i;:::-;19779:22;19798:1;19779:11;:22::i;15370:364::-;15512:4;15506:11;;15544:1;15531:15;;15588:3;15584:11;;;;15577:4;15567:15;;15560:36;15688:4;15678:15;;15665:29;;15506:11;15370:364::o;15100:110::-;15150:12;15182:20;15199:1;15193:8;;15182:10;:20::i;:::-;15175:27;15100:110;-1:-1:-1;;15100:110:0:o;15896:623::-;16042:4;16036:11;16076:4;16094:21;;;15950:12;;16036:11;16166:4;16202;16129:307;16233:7;16225:6;16222:19;16129:307;;;16418:1;16410:6;16405:15;16396:6;16389:4;16383;16379:15;16375:28;16367:54;16283:4;16271:17;;;;;-1:-1:-1;;16316:17:0;16129:307;;;-1:-1:-1;;;16473:4:0;16463:15;;16457:4;16450:29;16463:15;15896:623;-1:-1:-1;;15896:623:0:o;16681:620::-;16824:4;16818:11;16858:4;16876:21;;;16734:12;;16818:11;16948:4;16984;16911:307;17015:7;17007:6;17004:19;16911:307;;;17200:1;17192:6;17187:15;17178:6;17171:4;17165;17161:15;17157:28;17149:54;17065:4;17053:17;;;;;-1:-1:-1;;17098:17:0;16911:307;;;-1:-1:-1;;;17255:4:0;17245:15;;17239:4;17232:29;17245:15;16681:620;-1:-1:-1;;16681:620:0:o;17463:622::-;17608:4;17602:11;17642:4;17660:21;;;17516:12;;17602:11;17732:4;17768;17695:307;17799:7;17791:6;17788:19;17695:307;;;17984:1;17976:6;17971:15;17962:6;17955:4;17949;17945:15;17941:28;17933:54;17849:4;17837:17;;;;;-1:-1:-1;;17882:17:0;17695:307;;;-1:-1:-1;;;18039:4:0;18029:15;;18023:4;18016:29;18029:15;17463:622;-1:-1:-1;;17463:622:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::o
Swarm Source
ipfs://cf7112f021f9e2524cc4412d735952b2778a93a00ac3ae2b1657c7f004965357
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 83.94% | $0.000618 | 14,649,360.9296 | $9,046.71 | |
| ETH | 0.38% | $0.001697 | 24,291.7073 | $41.22 | |
| ETH | 0.01% | $0.00596 | 260.6777 | $1.55 | |
| ETH | <0.01% | $0.831612 | 1 | $0.8316 | |
| ETH | <0.01% | $0.000328 | 1,000 | $0.3278 | |
| BSC | 15.63% | $831.69 | 2.026 | $1,685.03 | |
| BSC | <0.01% | $0.999807 | 1 | $0.9998 | |
| BSC | <0.01% | <$0.000001 | 804,828 | $0.2918 | |
| POL | <0.01% | $0.104661 | 10 | $1.05 | |
| GNO | <0.01% | $0.999784 | 0.0697 | $0.069635 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.