Source Code
Latest 14 from a total of 14 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Lock | 16933362 | 1070 days ago | IN | 0 ETH | 0.00453746 | ||||
| Lock | 16933043 | 1070 days ago | IN | 0 ETH | 0.00444528 | ||||
| Lock | 15871876 | 1219 days ago | IN | 0.001 ETH | 0.00141886 | ||||
| Lock | 15866896 | 1219 days ago | IN | 0.001 ETH | 0.00064254 | ||||
| Lock | 15432676 | 1282 days ago | IN | 0.01 ETH | 0.00084381 | ||||
| Deposit | 15432659 | 1282 days ago | IN | 0.02 ETH | 0.00035512 | ||||
| Bind LP And Asse... | 15432614 | 1282 days ago | IN | 0 ETH | 0.00038933 | ||||
| Bind LP And Asse... | 15432612 | 1282 days ago | IN | 0 ETH | 0.0004778 | ||||
| Lock | 15414171 | 1285 days ago | IN | 0 ETH | 0.00132612 | ||||
| Bind Proxy Hash | 15414080 | 1285 days ago | IN | 0 ETH | 0.00033606 | ||||
| Bind Proxy Hash | 15414057 | 1285 days ago | IN | 0 ETH | 0.00045686 | ||||
| Set Manager Prox... | 15414049 | 1285 days ago | IN | 0 ETH | 0.00046251 | ||||
| Deposit | 15414040 | 1285 days ago | IN | 0 ETH | 0.00142454 | ||||
| Bind LP And Asse... | 15413495 | 1285 days ago | IN | 0 ETH | 0.00086486 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 15432827 | 1282 days ago | 0.01 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LockProxyPip4
Compiler Version
v0.5.0+commit.1d4f565a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;
import "./Ownable.sol";
import "./ZeroCopySource.sol";
import "./ZeroCopySink.sol";
import "./Utils.sol";
import "./SafeERC20.sol";
import "./ERC20Detailed.sol";
import "./Pausable.sol";
import "./IEthCrossChainManager.sol";
import "./IEthCrossChainManagerProxy.sol";
contract LockProxyPip4 is Ownable, Pausable {
using SafeMath for uint;
using SafeERC20 for IERC20;
uint8 constant StandardDecimals = 18;
struct TxArgs {
bytes toAssetHash;
bytes toAddress;
uint256 amount;
}
address public managerProxyContract;
mapping(uint64 => bytes) public proxyHashMap;
mapping(address => mapping(uint64 => bytes)) public assetHashMap;
mapping(address => address) public assetLPMap;
event SetManagerProxyEvent(address manager);
event BindProxyEvent(uint64 toChainId, bytes targetProxyHash);
event BindAssetEvent(address fromAssetHash, uint64 toChainId, bytes targetProxyHash, uint initialAmount);
event UnlockEvent(address toAssetHash, address toAddress, uint256 amount);
event LockEvent(address fromAssetHash, address fromAddress, uint64 toChainId, bytes toAssetHash, bytes toAddress, uint256 amount);
event depositEvent(address toAddress, address fromAssetHash, address fromLPHash, uint256 amount);
event withdrawEvent(address toAddress, address fromAssetHash, address fromLPHash, uint256 amount);
event BindLPToAssetEvent(address originAssetAddress, address LPTokenAddress);
modifier onlyManagerContract() {
IEthCrossChainManagerProxy ieccmp = IEthCrossChainManagerProxy(managerProxyContract);
require(_msgSender() == ieccmp.getEthCrossChainManager(), "msgSender is not EthCrossChainManagerContract");
_;
}
function pause() onlyOwner whenNotPaused public returns (bool) {
_pause();
return true;
}
function unpause() onlyOwner whenPaused public returns (bool) {
_unpause();
return true;
}
function setManagerProxy(address ethCCMProxyAddr) onlyOwner public {
managerProxyContract = ethCCMProxyAddr;
emit SetManagerProxyEvent(managerProxyContract);
}
function bindProxyHash(uint64 toChainId, bytes memory targetProxyHash) onlyOwner public returns (bool) {
proxyHashMap[toChainId] = targetProxyHash;
emit BindProxyEvent(toChainId, targetProxyHash);
return true;
}
function bindAssetHash(address fromAssetHash, uint64 toChainId, bytes memory toAssetHash) onlyOwner public returns (bool) {
assetHashMap[fromAssetHash][toChainId] = toAssetHash;
emit BindAssetEvent(fromAssetHash, toChainId, toAssetHash, getBalanceFor(fromAssetHash));
return true;
}
function bindLPToAsset(address originAssetAddress, address LPTokenAddress) onlyOwner public returns (bool) {
assetLPMap[originAssetAddress] = LPTokenAddress;
emit BindLPToAssetEvent(originAssetAddress, LPTokenAddress);
return true;
}
function bindLPAndAsset(address fromAssetHash, address fromLPHash, uint64 toChainId, bytes memory toAssetHash, bytes memory toLPHash) onlyOwner public returns (bool) {
assetHashMap[fromAssetHash][toChainId] = toAssetHash;
assetHashMap[fromLPHash][toChainId] = toLPHash;
assetLPMap[fromAssetHash] = fromLPHash;
emit BindAssetEvent(fromAssetHash, toChainId, toAssetHash, getBalanceFor(fromAssetHash));
emit BindAssetEvent(fromLPHash, toChainId, toLPHash, getBalanceFor(fromLPHash));
emit BindLPToAssetEvent(fromAssetHash, fromLPHash);
return true;
}
function bindProxyHashBatch(uint64[] memory toChainId, bytes[] memory targetProxyHash) onlyOwner public returns (bool) {
require(toChainId.length == targetProxyHash.length, "bindProxyHashBatch: args length diff");
for (uint i = 0; i < toChainId.length; i++) {
proxyHashMap[toChainId[i]] = targetProxyHash[i];
emit BindProxyEvent(toChainId[i], targetProxyHash[i]);
}
return true;
}
function bindAssetHashBatch(address[] memory fromAssetHash, uint64[] memory toChainId, bytes[] memory toAssetHash) onlyOwner public returns (bool) {
require(toChainId.length == fromAssetHash.length, "bindAssetHashBatch: args length diff");
require(toChainId.length == toAssetHash.length, "bindAssetHashBatch: args length diff");
for (uint i = 0; i < toChainId.length; i++) {
assetHashMap[fromAssetHash[i]][toChainId[i]] = toAssetHash[i];
emit BindAssetEvent(fromAssetHash[i], toChainId[i], toAssetHash[i], getBalanceFor(fromAssetHash[i]));
}
return true;
}
function bindLPToAssetBatch(address[] memory originAssetAddress, address[] memory LPTokenAddress) onlyOwner public returns (bool) {
require(originAssetAddress.length == LPTokenAddress.length, "bindLPToAssetBatch: args length diff");
for (uint i = 0; i < originAssetAddress.length; i++) {
assetLPMap[originAssetAddress[i]] = LPTokenAddress[i];
emit BindLPToAssetEvent(originAssetAddress[i], LPTokenAddress[i]);
}
return true;
}
function bindLPAndAssetBatch(address[] memory fromAssetHash, address[] memory fromLPHash, uint64[] memory toChainId, bytes[] memory toAssetHash, bytes[] memory toLPHash) onlyOwner public returns (bool) {
require(fromAssetHash.length == fromLPHash.length, "bindLPAndAssetBatch: args length diff");
require(toAssetHash.length == toLPHash.length, "bindLPAndAssetBatch: args length diff");
for(uint256 i = 0; i < fromLPHash.length; i++) {
assetHashMap[fromAssetHash[i]][toChainId[i]] = toAssetHash[i];
assetHashMap[fromLPHash[i]][toChainId[i]] = toLPHash[i];
assetLPMap[fromAssetHash[i]] = fromLPHash[i];
emit BindAssetEvent(fromAssetHash[i], toChainId[i], toAssetHash[i], getBalanceFor(fromAssetHash[i]));
emit BindAssetEvent(fromLPHash[i], toChainId[i], toLPHash[i], getBalanceFor(fromLPHash[i]));
emit BindLPToAssetEvent(fromAssetHash[i], fromLPHash[i]);
}
return true;
}
/* @notice This function is meant to be invoked by the user,
* a certain amount tokens will be locked in the proxy contract the invoker/msg.sender immediately.
* Then the same amount of tokens will be unloked from target chain proxy contract at the target chain with chainId later.
* @param fromAssetHash The asset address in current chain, uniformly named as `fromAssetHash`
* @param toChainId The target chain id
*
* @param toAddress The address in bytes format to receive same amount of tokens in target chain
* @param amount The amount of tokens to be crossed from ethereum to the chain with chainId
*/
function lock(address fromAssetHash, uint64 toChainId, bytes memory toAddress, uint256 amount) public payable returns (bool) {
require(amount != 0, "amount cannot be zero!");
require(_transferToContract(fromAssetHash, amount), "transfer asset from fromAddress to lock_proxy contract failed!");
bytes memory toAssetHash = assetHashMap[fromAssetHash][toChainId];
require(toAssetHash.length != 0, "empty illegal toAssetHash");
TxArgs memory txArgs = TxArgs({
toAssetHash: toAssetHash,
toAddress: toAddress,
amount: _toStandardDecimals(fromAssetHash, amount)
});
bytes memory txData = _serializeTxArgs(txArgs);
IEthCrossChainManagerProxy eccmp = IEthCrossChainManagerProxy(managerProxyContract);
address eccmAddr = eccmp.getEthCrossChainManager();
IEthCrossChainManager eccm = IEthCrossChainManager(eccmAddr);
bytes memory toProxyHash = proxyHashMap[toChainId];
require(toProxyHash.length != 0, "empty illegal toProxyHash");
require(eccm.crossChain(toChainId, toProxyHash, "unlock", txData), "EthCrossChainManager crossChain executed error!");
emit LockEvent(fromAssetHash, _msgSender(), toChainId, toAssetHash, toAddress, amount);
return true;
}
/* @notice This function is meant to be invoked by the ETH crosschain management contract,
* then mint a certin amount of tokens to the designated address since a certain amount
* was burnt from the source chain invoker.
* @param argsBs The argument bytes recevied by the ethereum lock proxy contract, need to be deserialized.
* based on the way of serialization in the source chain proxy contract.
* @param fromContractAddr The source chain contract address
* @param fromChainId The source chain id
*/
function unlock(bytes memory argsBs, bytes memory fromContractAddr, uint64 fromChainId) onlyManagerContract public returns (bool) {
TxArgs memory args = _deserializeTxArgs(argsBs);
require(fromContractAddr.length != 0, "from proxy contract address cannot be empty");
require(Utils.equalStorage(proxyHashMap[fromChainId], fromContractAddr), "From Proxy contract address error!");
require(args.toAssetHash.length != 0, "toAssetHash cannot be empty");
address toAssetHash = Utils.bytesToAddress(args.toAssetHash);
require(args.toAddress.length != 0, "toAddress cannot be empty");
address toAddress = Utils.bytesToAddress(args.toAddress);
uint amount = _fromStandardDecimals(toAssetHash, args.amount);
require(_transferFromContract(toAssetHash, toAddress, amount), "transfer asset from lock_proxy contract to toAddress failed!");
emit UnlockEvent(toAssetHash, toAddress, amount);
return true;
}
function deposit(address originAssetAddress, uint amount) whenNotPaused payable public returns (bool) {
require(amount != 0, "amount cannot be zero!");
require(_transferToContract(originAssetAddress, amount), "transfer asset from fromAddress to lock_proxy contract failed!");
address LPTokenAddress = assetLPMap[originAssetAddress];
require(LPTokenAddress != address(0), "do not support deposite this token");
uint standardAmount = _toStandardDecimals(originAssetAddress, amount);
uint lpAmount = _fromStandardDecimals(LPTokenAddress, standardAmount);
require(_transferFromContract(LPTokenAddress, msg.sender, lpAmount), "transfer proof of liquidity from lock_proxy contract to fromAddress failed!");
emit depositEvent(msg.sender, originAssetAddress, LPTokenAddress, amount);
return true;
}
function withdraw(address targetTokenAddress, uint lpAmount) whenNotPaused public returns (bool) {
require(lpAmount != 0, "amount cannot be zero!");
address LPTokenAddress = assetLPMap[targetTokenAddress];
require(LPTokenAddress != address(0), "do not support withdraw this token");
require(_transferToContract(LPTokenAddress, lpAmount), "transfer proof of liquidity from fromAddress to lock_proxy contract failed!");
uint standardAmount = _toStandardDecimals(LPTokenAddress, lpAmount);
uint amount = _fromStandardDecimals(targetTokenAddress, standardAmount);
require(_transferFromContract(targetTokenAddress, msg.sender, amount), "transfer asset from lock_proxy contract to fromAddress failed!");
emit withdrawEvent(msg.sender, targetTokenAddress, LPTokenAddress, amount);
return true;
}
function getBalanceFor(address fromAssetHash) public view returns (uint256) {
if (fromAssetHash == address(0)) {
// return address(this).balance; // this expression would result in error: Failed to decode output: Error: insufficient data for uint256 type
address selfAddr = address(this);
return selfAddr.balance;
} else {
IERC20 erc20Token = IERC20(fromAssetHash);
return erc20Token.balanceOf(address(this));
}
}
function _toStandardDecimals(address token, uint256 amount) internal view returns (uint256) {
uint8 decimals;
if (token == address(0)) {
decimals = 18;
} else {
decimals = ERC20Detailed(token).decimals();
}
if (decimals == StandardDecimals) {
return amount;
} else if (decimals < StandardDecimals) {
return amount * (10 ** uint(StandardDecimals - decimals));
} else {
return amount / (10 ** uint(decimals - StandardDecimals));
}
}
function _fromStandardDecimals(address token, uint256 standardAmount) internal view returns (uint256) {
uint8 decimals;
if (token == address(0)) {
decimals = 18;
} else {
decimals = ERC20Detailed(token).decimals();
}
if (decimals == StandardDecimals) {
return standardAmount;
} else if (decimals < StandardDecimals) {
return standardAmount / (10 ** uint(StandardDecimals - decimals));
} else {
return standardAmount * (10 ** uint(decimals - StandardDecimals));
}
}
function _transferToContract(address fromAssetHash, uint256 amount) internal returns (bool) {
if (fromAssetHash == address(0)) {
// fromAssetHash === address(0) denotes user choose to lock ether
// passively check if the received msg.value equals amount
require(msg.value != 0, "transferred ether cannot be zero!");
require(msg.value == amount, "transferred ether is not equal to amount!");
} else {
// make sure lockproxy contract will decline any received ether
require(msg.value == 0, "there should be no ether transfer!");
// actively transfer amount of asset from msg.sender to lock_proxy contract
require(_transferERC20ToContract(fromAssetHash, _msgSender(), address(this), amount), "transfer erc20 asset to lock_proxy contract failed!");
}
return true;
}
function _transferFromContract(address toAssetHash, address toAddress, uint256 amount) internal returns (bool) {
if (toAssetHash == address(0x0000000000000000000000000000000000000000)) {
// toAssetHash === address(0) denotes contract needs to unlock ether to toAddress
// convert toAddress from 'address' type to 'address payable' type, then actively transfer ether
address(uint160(toAddress)).transfer(amount);
} else {
// actively transfer amount of asset from msg.sender to lock_proxy contract
require(_transferERC20FromContract(toAssetHash, toAddress, amount), "transfer erc20 asset to lock_proxy contract failed!");
}
return true;
}
function _transferERC20ToContract(address fromAssetHash, address fromAddress, address toAddress, uint256 amount) internal returns (bool) {
IERC20 erc20Token = IERC20(fromAssetHash);
// require(erc20Token.transferFrom(fromAddress, toAddress, amount), "trasnfer ERC20 Token failed!");
erc20Token.safeTransferFrom(fromAddress, toAddress, amount);
return true;
}
function _transferERC20FromContract(address toAssetHash, address toAddress, uint256 amount) internal returns (bool) {
IERC20 erc20Token = IERC20(toAssetHash);
// require(erc20Token.transfer(toAddress, amount), "transfer ERC20 Token failed!");
erc20Token.safeTransfer(toAddress, amount);
return true;
}
function _serializeTxArgs(TxArgs memory args) internal pure returns (bytes memory) {
bytes memory buff;
buff = abi.encodePacked(
ZeroCopySink.WriteVarBytes(args.toAssetHash),
ZeroCopySink.WriteVarBytes(args.toAddress),
ZeroCopySink.WriteUint255(args.amount)
);
return buff;
}
function _deserializeTxArgs(bytes memory valueBs) internal pure returns (TxArgs memory) {
TxArgs memory args;
uint256 off = 0;
(args.toAssetHash, off) = ZeroCopySource.NextVarBytes(valueBs, off);
(args.toAddress, off) = ZeroCopySource.NextVarBytes(valueBs, off);
(args.amount, off) = ZeroCopySource.NextUint255(valueBs, off);
return args;
}
}pragma solidity ^0.5.0;
/**
* @dev Interface of the EthCrossChainManagerProxy for business contract like LockProxy to obtain the reliable EthCrossChainManager contract hash.
*/
interface IEthCrossChainManagerProxy {
function getEthCrossChainManager() external view returns (address);
}pragma solidity ^0.5.0;
/**
* @dev Interface of the EthCrossChainManager contract for business contract like LockProxy to request cross chain transaction
*/
interface IEthCrossChainManager {
function crossChain(uint64 _toChainId, bytes calldata _toContract, bytes calldata _method, bytes calldata _txData) external returns (bool);
}pragma solidity ^0.5.0;
import "./Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by a pauser (`account`).
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by a pauser (`account`).
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor () internal {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!_paused, "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(_paused, "Pausable: not paused");
_;
}
/**
* @dev Called to pause, triggers stopped state.
*/
function _pause() internal whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Called to unpause, returns to normal state.
*/
function _unpause() internal whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}pragma solidity ^0.5.0;
import "./IERC20.sol";
/**
* @dev Optional functions from the ERC20 standard.
* Refer from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20Detailed.sol
*/
contract ERC20Detailed is IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
* these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory name, string memory symbol, uint8 decimals) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view returns (uint8) {
return _decimals;
}
}pragma solidity ^0.5.0;
import "./IERC20.sol";
import "./SafeMath.sol";
import "./Utils.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// 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(Utils.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");
}
}
}pragma solidity ^0.5.0;
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);
}
}pragma solidity ^0.5.0;
/**
* @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)));
}
}
}pragma solidity ^0.5.0;
/**
* @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);
}
}
}pragma solidity ^0.5.0;
import "./Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}pragma solidity ^0.5.0;
/**
* @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.
*
* _Available since v2.4.0._
*/
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.
*
* _Available since v2.4.0._
*/
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.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}pragma solidity ^0.5.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}pragma solidity ^0.5.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
* Refer from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/GSN/Context.sol
*/
contract Context {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () internal { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"constant":false,"inputs":[{"name":"argsBs","type":"bytes"},{"name":"fromContractAddr","type":"bytes"},{"name":"fromChainId","type":"uint64"}],"name":"unlock","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"fromAssetHash","type":"address[]"},{"name":"fromLPHash","type":"address[]"},{"name":"toChainId","type":"uint64[]"},{"name":"toAssetHash","type":"bytes[]"},{"name":"toLPHash","type":"bytes[]"}],"name":"bindLPAndAssetBatch","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"toChainId","type":"uint64[]"},{"name":"targetProxyHash","type":"bytes[]"}],"name":"bindProxyHashBatch","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"fromAssetHash","type":"address"},{"name":"toChainId","type":"uint64"},{"name":"toAssetHash","type":"bytes"}],"name":"bindAssetHash","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"assetLPMap","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"toChainId","type":"uint64"},{"name":"targetProxyHash","type":"bytes"}],"name":"bindProxyHash","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"originAssetAddress","type":"address"},{"name":"amount","type":"uint256"}],"name":"deposit","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint64"}],"name":"assetHashMap","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fromAssetHash","type":"address"},{"name":"fromLPHash","type":"address"},{"name":"toChainId","type":"uint64"},{"name":"toAssetHash","type":"bytes"},{"name":"toLPHash","type":"bytes"}],"name":"bindLPAndAsset","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"fromAssetHash","type":"address"}],"name":"getBalanceFor","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"originAssetAddress","type":"address[]"},{"name":"LPTokenAddress","type":"address[]"}],"name":"bindLPToAssetBatch","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"originAssetAddress","type":"address"},{"name":"LPTokenAddress","type":"address"}],"name":"bindLPToAsset","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"fromAssetHash","type":"address[]"},{"name":"toChainId","type":"uint64[]"},{"name":"toAssetHash","type":"bytes[]"}],"name":"bindAssetHashBatch","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"fromAssetHash","type":"address"},{"name":"toChainId","type":"uint64"},{"name":"toAddress","type":"bytes"},{"name":"amount","type":"uint256"}],"name":"lock","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint64"}],"name":"proxyHashMap","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"ethCCMProxyAddr","type":"address"}],"name":"setManagerProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"managerProxyContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"targetTokenAddress","type":"address"},{"name":"lpAmount","type":"uint256"}],"name":"withdraw","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"manager","type":"address"}],"name":"SetManagerProxyEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"toChainId","type":"uint64"},{"indexed":false,"name":"targetProxyHash","type":"bytes"}],"name":"BindProxyEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fromAssetHash","type":"address"},{"indexed":false,"name":"toChainId","type":"uint64"},{"indexed":false,"name":"targetProxyHash","type":"bytes"},{"indexed":false,"name":"initialAmount","type":"uint256"}],"name":"BindAssetEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"toAssetHash","type":"address"},{"indexed":false,"name":"toAddress","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"UnlockEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fromAssetHash","type":"address"},{"indexed":false,"name":"fromAddress","type":"address"},{"indexed":false,"name":"toChainId","type":"uint64"},{"indexed":false,"name":"toAssetHash","type":"bytes"},{"indexed":false,"name":"toAddress","type":"bytes"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"LockEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"toAddress","type":"address"},{"indexed":false,"name":"fromAssetHash","type":"address"},{"indexed":false,"name":"fromLPHash","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"depositEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"toAddress","type":"address"},{"indexed":false,"name":"fromAssetHash","type":"address"},{"indexed":false,"name":"fromLPHash","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"withdrawEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"originAssetAddress","type":"address"},{"indexed":false,"name":"LPTokenAddress","type":"address"}],"name":"BindLPToAssetEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]Contract Creation Code
608060405260006200001964010000000062000079810204565b60008054600160a060020a031916600160a060020a0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506000805460a060020a60ff02191690556200007d565b3390565b6149b2806200008d6000396000f3fe60806040526004361061012f5763ffffffff60e060020a60003504166306af4b9f81146101345780630892cf481461016a57806325a9f9001461018a5780633348f63b146101aa5780633389279d146101ca578063379b98f6146101f75780633f4ba83a1461021757806347e7ef241461022c5780634f7d98081461023f57806353d1d2771461026c57806359c589a11461028c5780635c975abb146102b957806361c6617d146102ce5780636bc9e760146102ee5780636f3326d51461030e578063715018a61461032e5780638456cb591461034557806384a6d0551461035a5780638da5cb5b1461036d5780638f32d59b146103825780639e5767aa14610397578063af9980f0146103b7578063d798f881146103d7578063f2fde38b146103ec578063f3fef3a31461040c575b600080fd5b34801561014057600080fd5b5061015461014f3660046135e1565b61042c565b604051610161919061450e565b60405180910390f35b34801561017657600080fd5b506101546101853660046133fb565b610679565b34801561019657600080fd5b506101546101a5366004613564565b610a33565b3480156101b657600080fd5b506101546101c53660046132be565b610b73565b3480156101d657600080fd5b506101ea6101e5366004613143565b610c18565b60405161016191906143bb565b34801561020357600080fd5b5061015461021236600461368f565b610c33565b34801561022357600080fd5b50610154610ccb565b61015461023a36600461325e565b610d33565b34801561024b57600080fd5b5061025f61025a36600461328e565b610e7c565b604051610161919061451c565b34801561027857600080fd5b506101546102873660046131b9565b610f20565b34801561029857600080fd5b506102ac6102a7366004613143565b611083565b60405161016191906147cd565b3480156102c557600080fd5b5061015461113d565b3480156102da57600080fd5b506101546102e936600461339c565b61114d565b3480156102fa57600080fd5b5061015461030936600461317f565b61127d565b34801561031a57600080fd5b506101546103293660046134da565b611304565b34801561033a57600080fd5b506103436114ba565b005b34801561035157600080fd5b5061015461153a565b610154610368366004613323565b61159a565b34801561037957600080fd5b506101ea61197c565b34801561038e57600080fd5b5061015461198b565b3480156103a357600080fd5b5061025f6103b2366004613671565b6119af565b3480156103c357600080fd5b506103436103d2366004613143565b611a15565b3480156103e357600080fd5b506101ea611aa7565b3480156103f857600080fd5b50610343610407366004613143565b611ab6565b34801561041857600080fd5b5061015461042736600461325e565b611aeb565b600154604080517f87939a7f0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169182916387939a7f91600480820192602092909190829003018186803b15801561048d57600080fd5b505afa1580156104a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104c59190810190613161565b600160a060020a03166104d6611c20565b600160a060020a0316146105085760405160e560020a62461bcd0281526004016104ff9061462d565b60405180910390fd5b610510612e9a565b61051986611c24565b8551909150151561053f5760405160e560020a62461bcd0281526004016104ff9061464d565b67ffffffffffffffff841660009081526002602052604090206105629086611c70565b15156105835760405160e560020a62461bcd0281526004016104ff9061478d565b80515115156105a75760405160e560020a62461bcd0281526004016104ff906145cd565b60006105b68260000151611d26565b60208301515190915015156105e05760405160e560020a62461bcd0281526004016104ff906146cd565b60006105ef8360200151611d26565b90506000610601838560400151611d55565b905061060e838383611e39565b151561062f5760405160e560020a62461bcd0281526004016104ff906145fd565b7fd90288730b87c2b8e0c45bd82260fd22478aba30ae1c4d578b8daba9261604df8383836040516106629392919061448f565b60405180910390a150600198975050505050505050565b600061068361198b565b15156106a45760405160e560020a62461bcd0281526004016104ff9061467d565b84518651146106c85760405160e560020a62461bcd0281526004016104ff9061461d565b81518351146106ec5760405160e560020a62461bcd0281526004016104ff9061461d565b60005b8551811015610a2457838181518110151561070657fe5b9060200190602002015160036000898481518110151561072257fe5b90602001906020020151600160a060020a0316600160a060020a031681526020019081526020016000206000878481518110151561075c57fe5b9060200190602002015167ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020908051906020019061079b929190612ebc565b5082818151811015156107aa57fe5b906020019060200201516003600088848151811015156107c657fe5b90602001906020020151600160a060020a0316600160a060020a031681526020019081526020016000206000878481518110151561080057fe5b9060200190602002015167ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020908051906020019061083f929190612ebc565b50858181518110151561084e57fe5b9060200190602002015160046000898481518110151561086a57fe5b90602001906020020151600160a060020a0316600160a060020a0316815260200190815260200160002060006101000a815481600160a060020a030219169083600160a060020a0316021790555060008051602061495983398151915287828151811015156108d557fe5b9060200190602002015186838151811015156108ed57fe5b90602001906020020151868481518110151561090557fe5b9060200190602002015161092f8b8681518110151561092057fe5b90602001906020020151611083565b60405161093f94939291906144d2565b60405180910390a1600080516020614959833981519152868281518110151561096457fe5b90602001906020020151868381518110151561097c57fe5b90602001906020020151858481518110151561099457fe5b906020019060200201516109af8a8681518110151561092057fe5b6040516109bf94939291906144d2565b60405180910390a160008051602061493983398151915287828151811015156109e457fe5b9060200190602002015187838151811015156109fc57fe5b90602001906020020151604051610a1492919061440c565b60405180910390a16001016106ef565b50600190505b95945050505050565b6000610a3d61198b565b1515610a5e5760405160e560020a62461bcd0281526004016104ff9061467d565b8151835114610a825760405160e560020a62461bcd0281526004016104ff9061466d565b60005b8351811015610b67578281815181101515610a9c57fe5b90602001906020020151600260008684815181101515610ab857fe5b9060200190602002015167ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000209080519060200190610af7929190612ebc565b507fdacd7d303272a3b58aec6620d6d1fb588f4996a5b46858ed437f1c34348f2d0f8482815181101515610b2757fe5b906020019060200201518483815181101515610b3f57fe5b90602001906020020151604051610b579291906147db565b60405180910390a1600101610a85565b50600190505b92915050565b6000610b7d61198b565b1515610b9e5760405160e560020a62461bcd0281526004016104ff9061467d565b600160a060020a038416600090815260036020908152604080832067ffffffffffffffff8716845282529091208351610bd992850190612ebc565b50600080516020614959833981519152848484610bf588611083565b604051610c0594939291906144d2565b60405180910390a15060015b9392505050565b600460205260009081526040902054600160a060020a031681565b6000610c3d61198b565b1515610c5e5760405160e560020a62461bcd0281526004016104ff9061467d565b67ffffffffffffffff831660009081526002602090815260409091208351610c8892850190612ebc565b507fdacd7d303272a3b58aec6620d6d1fb588f4996a5b46858ed437f1c34348f2d0f8383604051610cba9291906147db565b60405180910390a150600192915050565b6000610cd561198b565b1515610cf65760405160e560020a62461bcd0281526004016104ff9061467d565b60005460a060020a900460ff161515610d245760405160e560020a62461bcd0281526004016104ff9061453d565b610d2c611ebd565b5060015b90565b6000805460a060020a900460ff1615610d615760405160e560020a62461bcd0281526004016104ff906145dd565b811515610d835760405160e560020a62461bcd0281526004016104ff9061459d565b610d8d8383611f49565b1515610dae5760405160e560020a62461bcd0281526004016104ff906145bd565b600160a060020a0380841660009081526004602052604090205416801515610deb5760405160e560020a62461bcd0281526004016104ff906145ed565b6000610df78585612002565b90506000610e058383611d55565b9050610e12833383611e39565b1515610e335760405160e560020a62461bcd0281526004016104ff906146dd565b7f30b853cf217db6b44a3d46920798a5308afc086c638198e6c161bd7fa12a1d3a33878588604051610e6894939291906143d7565b60405180910390a150600195945050505050565b60036020908152600092835260408084208252918352918190208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610f185780601f10610eed57610100808354040283529160200191610f18565b820191906000526020600020905b815481529060010190602001808311610efb57829003601f168201915b505050505081565b6000610f2a61198b565b1515610f4b5760405160e560020a62461bcd0281526004016104ff9061467d565b600160a060020a038616600090815260036020908152604080832067ffffffffffffffff8816845282529091208451610f8692860190612ebc565b50600160a060020a038516600090815260036020908152604080832067ffffffffffffffff8816845282529091208351610fc292850190612ebc565b50600160a060020a038681166000908152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff191691871691909117905560008051602061495983398151915286858561101983611083565b60405161102994939291906144d2565b60405180910390a160008051602061495983398151915285858461104c89611083565b60405161105c94939291906144d2565b60405180910390a16000805160206149398339815191528686604051610e6892919061440c565b6000600160a060020a038216151561109d57503031611138565b6040517f70a082310000000000000000000000000000000000000000000000000000000081528290600160a060020a038216906370a08231906110e49030906004016143bb565b60206040518083038186803b1580156110fc57600080fd5b505afa158015611110573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111349190810190613653565b9150505b919050565b60005460a060020a900460ff1690565b600061115761198b565b15156111785760405160e560020a62461bcd0281526004016104ff9061467d565b815183511461119c5760405160e560020a62461bcd0281526004016104ff906147bd565b60005b8351811015610b675782818151811015156111b657fe5b906020019060200201516004600086848151811015156111d257fe5b90602001906020020151600160a060020a0316600160a060020a0316815260200190815260200160002060006101000a815481600160a060020a030219169083600160a060020a03160217905550600080516020614939833981519152848281518110151561123d57fe5b90602001906020020151848381518110151561125557fe5b9060200190602002015160405161126d92919061440c565b60405180910390a160010161119f565b600061128761198b565b15156112a85760405160e560020a62461bcd0281526004016104ff9061467d565b600160a060020a0383811660009081526004602052604090819020805473ffffffffffffffffffffffffffffffffffffffff1916928516929092179091555160008051602061493983398151915290610cba908590859061440c565b600061130e61198b565b151561132f5760405160e560020a62461bcd0281526004016104ff9061467d565b83518351146113535760405160e560020a62461bcd0281526004016104ff9061470d565b81518351146113775760405160e560020a62461bcd0281526004016104ff9061470d565b60005b83518110156114af57828181518110151561139157fe5b906020019060200201516003600087848151811015156113ad57fe5b90602001906020020151600160a060020a0316600160a060020a03168152602001908152602001600020600086848151811015156113e757fe5b9060200190602002015167ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000209080519060200190611426929190612ebc565b50600080516020614959833981519152858281518110151561144457fe5b90602001906020020151858381518110151561145c57fe5b90602001906020020151858481518110151561147457fe5b9060200190602002015161148f898681518110151561092057fe5b60405161149f94939291906144d2565b60405180910390a160010161137a565b506001949350505050565b6114c261198b565b15156114e35760405160e560020a62461bcd0281526004016104ff9061467d565b60008054604051600160a060020a03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600061154461198b565b15156115655760405160e560020a62461bcd0281526004016104ff9061467d565b60005460a060020a900460ff16156115925760405160e560020a62461bcd0281526004016104ff906145dd565b610d2c6120dd565b60008115156115be5760405160e560020a62461bcd0281526004016104ff9061459d565b6115c88583611f49565b15156115e95760405160e560020a62461bcd0281526004016104ff906145bd565b600160a060020a038516600090815260036020908152604080832067ffffffffffffffff8816845282529182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084526060939283018282801561169a5780601f1061166f5761010080835404028352916020019161169a565b820191906000526020600020905b81548152906001019060200180831161167d57829003601f168201915b5050505050905080516000141515156116c85760405160e560020a62461bcd0281526004016104ff906146bd565b6116d0612e9a565b6060604051908101604052808381526020018681526020016116f28987612002565b90529050606061170182612157565b90506000600160009054906101000a9004600160a060020a03169050600081600160a060020a03166387939a7f6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561175b57600080fd5b505afa15801561176f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117939190810190613161565b67ffffffffffffffff8a16600090815260026020818152604092839020805484516001821615610100026000190190911693909304601f8101839004830284018301909452838352939450849360609390918301828280156118365780601f1061180b57610100808354040283529160200191611836565b820191906000526020600020905b81548152906001019060200180831161181957829003601f168201915b5050505050905080516000141515156118645760405160e560020a62461bcd0281526004016104ff9061460d565b6040517fbd5cf625000000000000000000000000000000000000000000000000000000008152600160a060020a0383169063bd5cf625906118ad908e9085908a906004016147fb565b602060405180830381600087803b1580156118c757600080fd5b505af11580156118db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506118ff91908101906135c3565b15156119205760405160e560020a62461bcd0281526004016104ff9061468d565b7f8636abd6d0e464fe725a13346c7ac779b73561c705506044a2e6b2cdb1295ea58c61194a611c20565b8d8a8e8e60405161196096959493929190614427565b60405180910390a160019750505050505050505b949350505050565b600054600160a060020a031690565b60008054600160a060020a03166119a0611c20565b600160a060020a031614905090565b600260208181526000928352604092839020805484516001821615610100026000190190911693909304601f8101839004830284018301909452838352919290830182828015610f185780601f10610eed57610100808354040283529160200191610f18565b611a1d61198b565b1515611a3e5760405160e560020a62461bcd0281526004016104ff9061467d565b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383811691909117918290556040517f43b1a8ec337adb61e8311ed025d99c80db65c02fe5c5027c1b6a93b40970cec492611a9c9216906143bb565b60405180910390a150565b600154600160a060020a031681565b611abe61198b565b1515611adf5760405160e560020a62461bcd0281526004016104ff9061467d565b611ae881612284565b50565b6000805460a060020a900460ff1615611b195760405160e560020a62461bcd0281526004016104ff906145dd565b811515611b3b5760405160e560020a62461bcd0281526004016104ff9061459d565b600160a060020a0380841660009081526004602052604090205416801515611b785760405160e560020a62461bcd0281526004016104ff9061476d565b611b828184611f49565b1515611ba35760405160e560020a62461bcd0281526004016104ff906146fd565b6000611baf8285612002565b90506000611bbd8683611d55565b9050611bca863383611e39565b1515611beb5760405160e560020a62461bcd0281526004016104ff9061452d565b7fcc7320d7ac24f61b5790719a3c0d7c3cdb569d0affd3996fd075136aa97fb51633878584604051610e6894939291906143d7565b3390565b611c2c612e9a565b611c34612e9a565b6000611c408482612317565b9083529050611c4f8482612317565b60208401919091529050611c6384826123d5565b5060408301525092915050565b60008060019050835460026001808316156101000203821604845180821460018114611c9f5760009450611d1a565b8215611d1a576020831060018114611cfd57600189600052602060002060208a018581015b600284828410011415611cf4578151835414611ce35760009950600093505b600183019250602082019150611cc4565b50505050611d18565b610100808604029450602088015185141515611d1857600095505b505b50929695505050505050565b8051600090601414611d4d5760405160e560020a62461bcd0281526004016104ff9061456d565b506014015190565b600080600160a060020a0384161515611d7057506012611de7565b83600160a060020a031663313ce5676040518163ffffffff1660e060020a02815260040160206040518083038186803b158015611dac57600080fd5b505afa158015611dc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611de491908101906136d7565b90505b60ff811660121415611dfc5782915050610b6d565b601260ff82161015611e25578060120360ff16600a0a83811515611e1c57fe5b04915050610b6d565b6012810360ff16600a0a8302915050610b6d565b6000600160a060020a0384161515611e8757604051600160a060020a0384169083156108fc029084906000818181858888f19350505050158015611e81573d6000803e3d6000fd5b50611eb3565b611e9284848461249f565b1515611eb35760405160e560020a62461bcd0281526004016104ff9061457d565b5060019392505050565b60005460a060020a900460ff161515611eeb5760405160e560020a62461bcd0281526004016104ff9061453d565b6000805474ff0000000000000000000000000000000000000000191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611f32611c20565b604051611f3f91906143c9565b60405180910390a1565b6000600160a060020a0383161515611fa457341515611f7d5760405160e560020a62461bcd0281526004016104ff906147ad565b348214611f9f5760405160e560020a62461bcd0281526004016104ff9061471d565b611ff9565b3415611fc55760405160e560020a62461bcd0281526004016104ff9061465d565b611fd883611fd1611c20565b30856124bc565b1515611ff95760405160e560020a62461bcd0281526004016104ff9061457d565b50600192915050565b600080600160a060020a038416151561201d57506012612094565b83600160a060020a031663313ce5676040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561205957600080fd5b505afa15801561206d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061209191908101906136d7565b90505b60ff8116601214156120a95782915050610b6d565b601260ff821610156120c9578060120360ff16600a0a8302915050610b6d565b6012810360ff16600a0a83811515611e1c57fe5b60005460a060020a900460ff161561210a5760405160e560020a62461bcd0281526004016104ff906145dd565b6000805474ff0000000000000000000000000000000000000000191660a060020a1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611f32611c20565b60608061216783600001516124e6565b61217484602001516124e6565b61218185604001516125ac565b6040516020018084805190602001908083835b602083106121b35780518252601f199092019160209182019101612194565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106121fb5780518252601f1990920191602091820191016121dc565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106122435780518252601f199092019160209182019101612224565b6001836020036101000a0380198251168184511680821785525050505050509050019350505050604051602081830303815290604052905080915050919050565b600160a060020a03811615156122af5760405160e560020a62461bcd0281526004016104ff9061458d565b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60606000806123268585612630565b865190955090915081850111801590612340575080840184105b15156123615760405160e560020a62461bcd0281526004016104ff9061477d565b60608115801561237c576040519150602082016040526123c6565b6040519150601f8316801560200281840101848101888315602002848c0101015b818310156123b557805183526020928301920161239d565b5050848452601f01601f1916604052505b509250830190505b9250929050565b600080835183602001111580156123ee57508260200183105b151561240f5760405160e560020a62461bcd0281526004016104ff9061454d565b600060405160206000600182038760208a0101515b838310156124445780821a83860153600183019250600182039150612424565b50505081016040525190507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156124925760405160e560020a62461bcd0281526004016104ff9061463d565b9460209390930193505050565b6000836114af600160a060020a038216858563ffffffff6127df16565b6000846124da600160a060020a03821686868663ffffffff61288316565b50600195945050505050565b80516060906124f4816128c6565b836040516020018083805190602001908083835b602083106125275780518252601f199092019160209182019101612508565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061256f5780518252601f199092019160209182019101612550565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052915050919050565b60607f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156125f15760405160e560020a62461bcd0281526004016104ff906146ad565b60405160208082526000601f5b828210156126205785811a8260208601015360019190910190600019016125fe565b5050506040818101905292915050565b600080600061263f8585612a47565b9450905060007ffd00000000000000000000000000000000000000000000000000000000000000600160f860020a0319831614156126c9576126818686612a95565b955061ffff16905060fd811080159061269c575061ffff8111155b15156126bd5760405160e560020a62461bcd0281526004016104ff9061455d565b92508391506123ce9050565b7ffe00000000000000000000000000000000000000000000000000000000000000600160f860020a031983161415612745576127058686612b04565b955063ffffffff16905061ffff81118015612724575063ffffffff8111155b15156126bd5760405160e560020a62461bcd0281526004016104ff906146ed565b600160f860020a03198083161415612795576127618686612b90565b955067ffffffffffffffff16905063ffffffff81116126bd5760405160e560020a62461bcd0281526004016104ff906146ed565b5060ff7f010000000000000000000000000000000000000000000000000000000000000082041660fd81106126bd5760405160e560020a62461bcd0281526004016104ff906146ed565b60405161287e9084907fa9059cbb000000000000000000000000000000000000000000000000000000009061281a90869086906024016144b7565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612c1c565b505050565b6040516128c09085907f23b872dd000000000000000000000000000000000000000000000000000000009061281a9087908790879060240161448f565b50505050565b606060fd8267ffffffffffffffff1610156128eb576128e482612d51565b9050611138565b61ffff67ffffffffffffffff8316116129e6576129277ffd00000000000000000000000000000000000000000000000000000000000000612d6d565b61293083612d9a565b6040516020018083805190602001908083835b602083106129625780518252601f199092019160209182019101612943565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106129aa5780518252601f19909201916020918201910161298b565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529050611138565b63ffffffff67ffffffffffffffff831611612a2d57612a247ffe00000000000000000000000000000000000000000000000000000000000000612d6d565b61293083612ddd565b612a3e600160f860020a0319612d6d565b61293083612e20565b60008083518360010111158015612a6057508260010183105b1515612a815760405160e560020a62461bcd0281526004016104ff9061469d565b505081810160200151600182019250929050565b60008083518360020111158015612aae57508260020183105b1515612acf5760405160e560020a62461bcd0281526004016104ff9061472d565b6000604051846020870101518060011a82538060001a6001830153506002818101604052601d19909101519694019450505050565b60008083518360040111158015612b1d57508260040183105b1515612b3e5760405160e560020a62461bcd0281526004016104ff9061475d565b600060405160046000600182038760208a0101515b83831015612b735780821a83860153600183019250600182039150612b53565b505050808201604052602003900351956004949094019450505050565b60008083518360080111158015612ba957508260080183105b1515612bca5760405160e560020a62461bcd0281526004016104ff9061474d565b600060405160086000600182038760208a0101515b83831015612bff5780821a83860153600183019250600182039150612bdf565b505050808201604052602003900351956008949094019450505050565b612c2582612e63565b1515612c465760405160e560020a62461bcd0281526004016104ff9061479d565b6000606083600160a060020a0316836040518082805190602001908083835b60208310612c845780518252601f199092019160209182019101612c65565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612ce6576040519150601f19603f3d011682016040523d82523d6000602084013e612ceb565b606091505b5091509150811515612d125760405160e560020a62461bcd0281526004016104ff906145ad565b6000815111156128c05780806020019051612d3091908101906135c3565b15156128c05760405160e560020a62461bcd0281526004016104ff9061473d565b604080516001815260f89290921b602083015260218201905290565b6060610b6d7f01000000000000000000000000000000000000000000000000000000000000008304612d51565b6040516002808252606091906000601f5b82821015612dcd5785811a826020860101536001919091019060001901612dab565b5050506022810160405292915050565b6040516004808252606091906000601f5b82821015612e105785811a826020860101536001919091019060001901612dee565b5050506024810160405292915050565b6040516008808252606091906000601f5b82821015612e535785811a826020860101536001919091019060001901612e31565b5050506028810160405292915050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906119745750141592915050565b6060604051908101604052806060815260200160608152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612efd57805160ff1916838001178555612f2a565b82800160010185558215612f2a579182015b82811115612f2a578251825591602001919060010190612f0f565b50612f36929150612f3a565b5090565b610d3091905b80821115612f365760008155600101612f40565b6000610c1182356148b6565b6000610c1182516148b6565b6000601f82018313612f7d57600080fd5b8135612f90612f8b82614869565b614842565b91508181835260208401935060208101905083856020840282011115612fb557600080fd5b60005b83811015612fe15781612fcb8882612f54565b8452506020928301929190910190600101612fb8565b5050505092915050565b6000601f82018313612ffc57600080fd5b813561300a612f8b82614869565b81815260209384019390925082018360005b83811015612fe1578135860161303288826130c4565b845250602092830192919091019060010161301c565b6000601f8201831361305957600080fd5b8135613067612f8b82614869565b9150818183526020840193506020810190508385602084028201111561308c57600080fd5b60005b83811015612fe157816130a2888261312b565b845250602092830192919091019060010161308f565b6000610c1182516148c1565b6000601f820183136130d557600080fd5b81356130e3612f8b8261488a565b915080825260208301602083018583830111156130ff57600080fd5b61310a8382846148f6565b50505092915050565b6000610c118235610d30565b6000610c118251610d30565b6000610c1182356148d2565b6000610c1182516148df565b60006020828403121561315557600080fd5b60006119748484612f54565b60006020828403121561317357600080fd5b60006119748484612f60565b6000806040838503121561319257600080fd5b600061319e8585612f54565b92505060206131af85828601612f54565b9150509250929050565b600080600080600060a086880312156131d157600080fd5b60006131dd8888612f54565b95505060206131ee88828901612f54565b94505060406131ff8882890161312b565b935050606086013567ffffffffffffffff81111561321c57600080fd5b613228888289016130c4565b925050608086013567ffffffffffffffff81111561324557600080fd5b613251888289016130c4565b9150509295509295909350565b6000806040838503121561327157600080fd5b600061327d8585612f54565b92505060206131af85828601613113565b600080604083850312156132a157600080fd5b60006132ad8585612f54565b92505060206131af8582860161312b565b6000806000606084860312156132d357600080fd5b60006132df8686612f54565b93505060206132f08682870161312b565b925050604084013567ffffffffffffffff81111561330d57600080fd5b613319868287016130c4565b9150509250925092565b6000806000806080858703121561333957600080fd5b60006133458787612f54565b94505060206133568782880161312b565b935050604085013567ffffffffffffffff81111561337357600080fd5b61337f878288016130c4565b925050606061339087828801613113565b91505092959194509250565b600080604083850312156133af57600080fd5b823567ffffffffffffffff8111156133c657600080fd5b6133d285828601612f6c565b925050602083013567ffffffffffffffff8111156133ef57600080fd5b6131af85828601612f6c565b600080600080600060a0868803121561341357600080fd5b853567ffffffffffffffff81111561342a57600080fd5b61343688828901612f6c565b955050602086013567ffffffffffffffff81111561345357600080fd5b61345f88828901612f6c565b945050604086013567ffffffffffffffff81111561347c57600080fd5b61348888828901613048565b935050606086013567ffffffffffffffff8111156134a557600080fd5b6134b188828901612feb565b925050608086013567ffffffffffffffff8111156134ce57600080fd5b61325188828901612feb565b6000806000606084860312156134ef57600080fd5b833567ffffffffffffffff81111561350657600080fd5b61351286828701612f6c565b935050602084013567ffffffffffffffff81111561352f57600080fd5b61353b86828701613048565b925050604084013567ffffffffffffffff81111561355857600080fd5b61331986828701612feb565b6000806040838503121561357757600080fd5b823567ffffffffffffffff81111561358e57600080fd5b61359a85828601613048565b925050602083013567ffffffffffffffff8111156135b757600080fd5b6131af85828601612feb565b6000602082840312156135d557600080fd5b600061197484846130b8565b6000806000606084860312156135f657600080fd5b833567ffffffffffffffff81111561360d57600080fd5b613619868287016130c4565b935050602084013567ffffffffffffffff81111561363657600080fd5b613642868287016130c4565b92505060406133198682870161312b565b60006020828403121561366557600080fd5b6000611974848461311f565b60006020828403121561368357600080fd5b6000611974848461312b565b600080604083850312156136a257600080fd5b60006136ae858561312b565b925050602083013567ffffffffffffffff8111156136cb57600080fd5b6131af858286016130c4565b6000602082840312156136e957600080fd5b60006119748484613137565b6136fe816148e5565b82525050565b6136fe816148b6565b6136fe816148c1565b6000613721826148b2565b808452613735816020860160208601614902565b61373e8161492e565b9093016020019392505050565b603e81527f7472616e736665722061737365742066726f6d206c6f636b5f70726f7879206360208201527f6f6e747261637420746f2066726f6d41646472657373206661696c6564210000604082015260600190565b601481527f5061757361626c653a206e6f7420706175736564000000000000000000000000602082015260400190565b602381527f4e65787455696e743235352c206f66667365742065786365656473206d61786960208201527f6d756d0000000000000000000000000000000000000000000000000000000000604082015260600190565b601f81527f4e65787455696e7431362c2076616c7565206f7574736964652072616e676500602082015260400190565b602381527f6279746573206c656e67746820646f6573206e6f74206d61746368206164647260208201527f6573730000000000000000000000000000000000000000000000000000000000604082015260600190565b603381527f7472616e7366657220657263323020617373657420746f206c6f636b5f70726f60208201527f787920636f6e7472616374206661696c65642100000000000000000000000000604082015260600190565b602681527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160208201527f6464726573730000000000000000000000000000000000000000000000000000604082015260600190565b601681527f616d6f756e742063616e6e6f74206265207a65726f2100000000000000000000602082015260400190565b60208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260400190565b603e81527f7472616e736665722061737365742066726f6d2066726f6d416464726573732060208201527f746f206c6f636b5f70726f787920636f6e7472616374206661696c6564210000604082015260600190565b601b81527f746f4173736574486173682063616e6e6f7420626520656d7074790000000000602082015260400190565b601081527f5061757361626c653a2070617573656400000000000000000000000000000000602082015260400190565b602281527f646f206e6f7420737570706f7274206465706f73697465207468697320746f6b60208201527f656e000000000000000000000000000000000000000000000000000000000000604082015260600190565b603c81527f7472616e736665722061737365742066726f6d206c6f636b5f70726f7879206360208201527f6f6e747261637420746f20746f41646472657373206661696c65642100000000604082015260600190565b601981527f656d70747920696c6c6567616c20746f50726f78794861736800000000000000602082015260400190565b602581527f62696e644c50416e64417373657442617463683a2061726773206c656e67746860208201527f2064696666000000000000000000000000000000000000000000000000000000604082015260600190565b602d81527f6d736753656e646572206973206e6f742045746843726f7373436861696e4d6160208201527f6e61676572436f6e747261637400000000000000000000000000000000000000604082015260600190565b601781527f56616c75652065786365656473207468652072616e6765000000000000000000602082015260400190565b602b81527f66726f6d2070726f787920636f6e747261637420616464726573732063616e6e60208201527f6f7420626520656d707479000000000000000000000000000000000000000000604082015260600190565b602281527f74686572652073686f756c64206265206e6f206574686572207472616e73666560208201527f7221000000000000000000000000000000000000000000000000000000000000604082015260600190565b602481527f62696e6450726f78794861736842617463683a2061726773206c656e6774682060208201527f6469666600000000000000000000000000000000000000000000000000000000604082015260600190565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65729082015260400190565b602f81527f45746843726f7373436861696e4d616e616765722063726f7373436861696e2060208201527f6578656375746564206572726f72210000000000000000000000000000000000604082015260600190565b60208082527f4e657874427974652c204f66667365742065786365656473206d6178696d756d9082015260400190565b600681527f756e6c6f636b0000000000000000000000000000000000000000000000000000602082015260400190565b601b81527f56616c756520657863656564732075696e743235352072616e67650000000000602082015260400190565b601981527f656d70747920696c6c6567616c20746f41737365744861736800000000000000602082015260400190565b601981527f746f416464726573732063616e6e6f7420626520656d70747900000000000000602082015260400190565b604b81527f7472616e736665722070726f6f66206f66206c69717569646974792066726f6d60208201527f206c6f636b5f70726f787920636f6e747261637420746f2066726f6d4164647260408201527f657373206661696c656421000000000000000000000000000000000000000000606082015260800190565b60208082527f4e65787456617255696e742c2076616c7565206f7574736964652072616e67659082015260400190565b604b81527f7472616e736665722070726f6f66206f66206c69717569646974792066726f6d60208201527f2066726f6d4164647265737320746f206c6f636b5f70726f787920636f6e747260408201527f616374206661696c656421000000000000000000000000000000000000000000606082015260800190565b602481527f62696e6441737365744861736842617463683a2061726773206c656e6774682060208201527f6469666600000000000000000000000000000000000000000000000000000000604082015260600190565b602981527f7472616e73666572726564206574686572206973206e6f7420657175616c207460208201527f6f20616d6f756e74210000000000000000000000000000000000000000000000604082015260600190565b602281527f4e65787455696e7431362c206f66667365742065786365656473206d6178696d60208201527f756d000000000000000000000000000000000000000000000000000000000000604082015260600190565b602a81527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60208201527f6f74207375636365656400000000000000000000000000000000000000000000604082015260600190565b602281527f4e65787455696e7436342c206f66667365742065786365656473206d6178696d60208201527f756d000000000000000000000000000000000000000000000000000000000000604082015260600190565b602281527f4e65787455696e7433322c206f66667365742065786365656473206d6178696d60208201527f756d000000000000000000000000000000000000000000000000000000000000604082015260600190565b602281527f646f206e6f7420737570706f7274207769746864726177207468697320746f6b60208201527f656e000000000000000000000000000000000000000000000000000000000000604082015260600190565b602481527f4e65787456617242797465732c206f66667365742065786365656473206d617860208201527f696d756d00000000000000000000000000000000000000000000000000000000604082015260600190565b602281527f46726f6d2050726f787920636f6e74726163742061646472657373206572726f60208201527f7221000000000000000000000000000000000000000000000000000000000000604082015260600190565b601f81527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400602082015260400190565b602181527f7472616e736665727265642065746865722063616e6e6f74206265207a65726f60208201527f2100000000000000000000000000000000000000000000000000000000000000604082015260600190565b602481527f62696e644c50546f417373657442617463683a2061726773206c656e6774682060208201527f6469666600000000000000000000000000000000000000000000000000000000604082015260600190565b6136fe81610d30565b6136fe816148d2565b60208101610b6d8284613704565b60208101610b6d82846136f5565b608081016143e582876136f5565b6143f26020830186613704565b6143ff6040830185613704565b610a2a60608301846143a9565b6040810161441a8285613704565b610c116020830184613704565b60c081016144358289613704565b61444260208301886136f5565b61444f60408301876143b2565b81810360608301526144618186613716565b905081810360808301526144758185613716565b905061448460a08301846143a9565b979650505050505050565b6060810161449d8286613704565b6144aa6020830185613704565b61197460408301846143a9565b604081016144c58285613704565b610c1160208301846143a9565b608081016144e08287613704565b6144ed60208301866143b2565b81810360408301526144ff8185613716565b9050610a2a60608301846143a9565b60208101610b6d828461370d565b60208082528101610c118184613716565b60208082528101610b6d8161374b565b60208082528101610b6d816137a1565b60208082528101610b6d816137d1565b60208082528101610b6d81613827565b60208082528101610b6d81613857565b60208082528101610b6d816138ad565b60208082528101610b6d81613903565b60208082528101610b6d81613959565b60208082528101610b6d81613989565b60208082528101610b6d816139b9565b60208082528101610b6d81613a0f565b60208082528101610b6d81613a3f565b60208082528101610b6d81613a6f565b60208082528101610b6d81613ac5565b60208082528101610b6d81613b1b565b60208082528101610b6d81613b4b565b60208082528101610b6d81613ba1565b60208082528101610b6d81613bf7565b60208082528101610b6d81613c27565b60208082528101610b6d81613c7d565b60208082528101610b6d81613cd3565b60208082528101610b6d81613d29565b60208082528101610b6d81613d59565b60208082528101610b6d81613daf565b60208082528101610b6d81613e0f565b60208082528101610b6d81613e3f565b60208082528101610b6d81613e6f565b60208082528101610b6d81613e9f565b60208082528101610b6d81613f1b565b60208082528101610b6d81613f4b565b60208082528101610b6d81613fc7565b60208082528101610b6d8161401d565b60208082528101610b6d81614073565b60208082528101610b6d816140c9565b60208082528101610b6d8161411f565b60208082528101610b6d81614175565b60208082528101610b6d816141cb565b60208082528101610b6d81614221565b60208082528101610b6d81614277565b60208082528101610b6d816142cd565b60208082528101610b6d816142fd565b60208082528101610b6d81614353565b60208101610b6d82846143a9565b604081016147e982856143b2565b81810360208301526119748184613716565b6080810161480982866143b2565b818103602083015261481b8185613716565b9050818103604083015261482e81613ddf565b90508181036060830152610a2a8184613716565b60405181810167ffffffffffffffff8111828210171561486157600080fd5b604052919050565b600067ffffffffffffffff82111561488057600080fd5b5060209081020190565b600067ffffffffffffffff8211156148a157600080fd5b506020601f91909101601f19160190565b5190565b6000610b6d826148c6565b151590565b600160a060020a031690565b67ffffffffffffffff1690565b60ff1690565b6000610b6d826000610b6d826148b6565b82818337506000910152565b60005b8381101561491d578181015183820152602001614905565b838111156128c05750506000910152565b601f01601f19169056fe2319c5345cde8ceb76a957b55d75082616215452400c34305e4e6adaaf42f7111628c8374c1bdfeb2275fd9f4c90562fd3fae974783dc522c8234e36abcfc58ea265627a7a7230582020e650bbca43da1a3f03f61b6e4460b77b50ae1c6d0bf83e2d2b0d5522f0cac36c6578706572696d656e74616cf50037
Deployed Bytecode
0x60806040526004361061012f5763ffffffff60e060020a60003504166306af4b9f81146101345780630892cf481461016a57806325a9f9001461018a5780633348f63b146101aa5780633389279d146101ca578063379b98f6146101f75780633f4ba83a1461021757806347e7ef241461022c5780634f7d98081461023f57806353d1d2771461026c57806359c589a11461028c5780635c975abb146102b957806361c6617d146102ce5780636bc9e760146102ee5780636f3326d51461030e578063715018a61461032e5780638456cb591461034557806384a6d0551461035a5780638da5cb5b1461036d5780638f32d59b146103825780639e5767aa14610397578063af9980f0146103b7578063d798f881146103d7578063f2fde38b146103ec578063f3fef3a31461040c575b600080fd5b34801561014057600080fd5b5061015461014f3660046135e1565b61042c565b604051610161919061450e565b60405180910390f35b34801561017657600080fd5b506101546101853660046133fb565b610679565b34801561019657600080fd5b506101546101a5366004613564565b610a33565b3480156101b657600080fd5b506101546101c53660046132be565b610b73565b3480156101d657600080fd5b506101ea6101e5366004613143565b610c18565b60405161016191906143bb565b34801561020357600080fd5b5061015461021236600461368f565b610c33565b34801561022357600080fd5b50610154610ccb565b61015461023a36600461325e565b610d33565b34801561024b57600080fd5b5061025f61025a36600461328e565b610e7c565b604051610161919061451c565b34801561027857600080fd5b506101546102873660046131b9565b610f20565b34801561029857600080fd5b506102ac6102a7366004613143565b611083565b60405161016191906147cd565b3480156102c557600080fd5b5061015461113d565b3480156102da57600080fd5b506101546102e936600461339c565b61114d565b3480156102fa57600080fd5b5061015461030936600461317f565b61127d565b34801561031a57600080fd5b506101546103293660046134da565b611304565b34801561033a57600080fd5b506103436114ba565b005b34801561035157600080fd5b5061015461153a565b610154610368366004613323565b61159a565b34801561037957600080fd5b506101ea61197c565b34801561038e57600080fd5b5061015461198b565b3480156103a357600080fd5b5061025f6103b2366004613671565b6119af565b3480156103c357600080fd5b506103436103d2366004613143565b611a15565b3480156103e357600080fd5b506101ea611aa7565b3480156103f857600080fd5b50610343610407366004613143565b611ab6565b34801561041857600080fd5b5061015461042736600461325e565b611aeb565b600154604080517f87939a7f0000000000000000000000000000000000000000000000000000000081529051600092600160a060020a03169182916387939a7f91600480820192602092909190829003018186803b15801561048d57600080fd5b505afa1580156104a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506104c59190810190613161565b600160a060020a03166104d6611c20565b600160a060020a0316146105085760405160e560020a62461bcd0281526004016104ff9061462d565b60405180910390fd5b610510612e9a565b61051986611c24565b8551909150151561053f5760405160e560020a62461bcd0281526004016104ff9061464d565b67ffffffffffffffff841660009081526002602052604090206105629086611c70565b15156105835760405160e560020a62461bcd0281526004016104ff9061478d565b80515115156105a75760405160e560020a62461bcd0281526004016104ff906145cd565b60006105b68260000151611d26565b60208301515190915015156105e05760405160e560020a62461bcd0281526004016104ff906146cd565b60006105ef8360200151611d26565b90506000610601838560400151611d55565b905061060e838383611e39565b151561062f5760405160e560020a62461bcd0281526004016104ff906145fd565b7fd90288730b87c2b8e0c45bd82260fd22478aba30ae1c4d578b8daba9261604df8383836040516106629392919061448f565b60405180910390a150600198975050505050505050565b600061068361198b565b15156106a45760405160e560020a62461bcd0281526004016104ff9061467d565b84518651146106c85760405160e560020a62461bcd0281526004016104ff9061461d565b81518351146106ec5760405160e560020a62461bcd0281526004016104ff9061461d565b60005b8551811015610a2457838181518110151561070657fe5b9060200190602002015160036000898481518110151561072257fe5b90602001906020020151600160a060020a0316600160a060020a031681526020019081526020016000206000878481518110151561075c57fe5b9060200190602002015167ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020908051906020019061079b929190612ebc565b5082818151811015156107aa57fe5b906020019060200201516003600088848151811015156107c657fe5b90602001906020020151600160a060020a0316600160a060020a031681526020019081526020016000206000878481518110151561080057fe5b9060200190602002015167ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020908051906020019061083f929190612ebc565b50858181518110151561084e57fe5b9060200190602002015160046000898481518110151561086a57fe5b90602001906020020151600160a060020a0316600160a060020a0316815260200190815260200160002060006101000a815481600160a060020a030219169083600160a060020a0316021790555060008051602061495983398151915287828151811015156108d557fe5b9060200190602002015186838151811015156108ed57fe5b90602001906020020151868481518110151561090557fe5b9060200190602002015161092f8b8681518110151561092057fe5b90602001906020020151611083565b60405161093f94939291906144d2565b60405180910390a1600080516020614959833981519152868281518110151561096457fe5b90602001906020020151868381518110151561097c57fe5b90602001906020020151858481518110151561099457fe5b906020019060200201516109af8a8681518110151561092057fe5b6040516109bf94939291906144d2565b60405180910390a160008051602061493983398151915287828151811015156109e457fe5b9060200190602002015187838151811015156109fc57fe5b90602001906020020151604051610a1492919061440c565b60405180910390a16001016106ef565b50600190505b95945050505050565b6000610a3d61198b565b1515610a5e5760405160e560020a62461bcd0281526004016104ff9061467d565b8151835114610a825760405160e560020a62461bcd0281526004016104ff9061466d565b60005b8351811015610b67578281815181101515610a9c57fe5b90602001906020020151600260008684815181101515610ab857fe5b9060200190602002015167ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000209080519060200190610af7929190612ebc565b507fdacd7d303272a3b58aec6620d6d1fb588f4996a5b46858ed437f1c34348f2d0f8482815181101515610b2757fe5b906020019060200201518483815181101515610b3f57fe5b90602001906020020151604051610b579291906147db565b60405180910390a1600101610a85565b50600190505b92915050565b6000610b7d61198b565b1515610b9e5760405160e560020a62461bcd0281526004016104ff9061467d565b600160a060020a038416600090815260036020908152604080832067ffffffffffffffff8716845282529091208351610bd992850190612ebc565b50600080516020614959833981519152848484610bf588611083565b604051610c0594939291906144d2565b60405180910390a15060015b9392505050565b600460205260009081526040902054600160a060020a031681565b6000610c3d61198b565b1515610c5e5760405160e560020a62461bcd0281526004016104ff9061467d565b67ffffffffffffffff831660009081526002602090815260409091208351610c8892850190612ebc565b507fdacd7d303272a3b58aec6620d6d1fb588f4996a5b46858ed437f1c34348f2d0f8383604051610cba9291906147db565b60405180910390a150600192915050565b6000610cd561198b565b1515610cf65760405160e560020a62461bcd0281526004016104ff9061467d565b60005460a060020a900460ff161515610d245760405160e560020a62461bcd0281526004016104ff9061453d565b610d2c611ebd565b5060015b90565b6000805460a060020a900460ff1615610d615760405160e560020a62461bcd0281526004016104ff906145dd565b811515610d835760405160e560020a62461bcd0281526004016104ff9061459d565b610d8d8383611f49565b1515610dae5760405160e560020a62461bcd0281526004016104ff906145bd565b600160a060020a0380841660009081526004602052604090205416801515610deb5760405160e560020a62461bcd0281526004016104ff906145ed565b6000610df78585612002565b90506000610e058383611d55565b9050610e12833383611e39565b1515610e335760405160e560020a62461bcd0281526004016104ff906146dd565b7f30b853cf217db6b44a3d46920798a5308afc086c638198e6c161bd7fa12a1d3a33878588604051610e6894939291906143d7565b60405180910390a150600195945050505050565b60036020908152600092835260408084208252918352918190208054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015610f185780601f10610eed57610100808354040283529160200191610f18565b820191906000526020600020905b815481529060010190602001808311610efb57829003601f168201915b505050505081565b6000610f2a61198b565b1515610f4b5760405160e560020a62461bcd0281526004016104ff9061467d565b600160a060020a038616600090815260036020908152604080832067ffffffffffffffff8816845282529091208451610f8692860190612ebc565b50600160a060020a038516600090815260036020908152604080832067ffffffffffffffff8816845282529091208351610fc292850190612ebc565b50600160a060020a038681166000908152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff191691871691909117905560008051602061495983398151915286858561101983611083565b60405161102994939291906144d2565b60405180910390a160008051602061495983398151915285858461104c89611083565b60405161105c94939291906144d2565b60405180910390a16000805160206149398339815191528686604051610e6892919061440c565b6000600160a060020a038216151561109d57503031611138565b6040517f70a082310000000000000000000000000000000000000000000000000000000081528290600160a060020a038216906370a08231906110e49030906004016143bb565b60206040518083038186803b1580156110fc57600080fd5b505afa158015611110573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111349190810190613653565b9150505b919050565b60005460a060020a900460ff1690565b600061115761198b565b15156111785760405160e560020a62461bcd0281526004016104ff9061467d565b815183511461119c5760405160e560020a62461bcd0281526004016104ff906147bd565b60005b8351811015610b675782818151811015156111b657fe5b906020019060200201516004600086848151811015156111d257fe5b90602001906020020151600160a060020a0316600160a060020a0316815260200190815260200160002060006101000a815481600160a060020a030219169083600160a060020a03160217905550600080516020614939833981519152848281518110151561123d57fe5b90602001906020020151848381518110151561125557fe5b9060200190602002015160405161126d92919061440c565b60405180910390a160010161119f565b600061128761198b565b15156112a85760405160e560020a62461bcd0281526004016104ff9061467d565b600160a060020a0383811660009081526004602052604090819020805473ffffffffffffffffffffffffffffffffffffffff1916928516929092179091555160008051602061493983398151915290610cba908590859061440c565b600061130e61198b565b151561132f5760405160e560020a62461bcd0281526004016104ff9061467d565b83518351146113535760405160e560020a62461bcd0281526004016104ff9061470d565b81518351146113775760405160e560020a62461bcd0281526004016104ff9061470d565b60005b83518110156114af57828181518110151561139157fe5b906020019060200201516003600087848151811015156113ad57fe5b90602001906020020151600160a060020a0316600160a060020a03168152602001908152602001600020600086848151811015156113e757fe5b9060200190602002015167ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000209080519060200190611426929190612ebc565b50600080516020614959833981519152858281518110151561144457fe5b90602001906020020151858381518110151561145c57fe5b90602001906020020151858481518110151561147457fe5b9060200190602002015161148f898681518110151561092057fe5b60405161149f94939291906144d2565b60405180910390a160010161137a565b506001949350505050565b6114c261198b565b15156114e35760405160e560020a62461bcd0281526004016104ff9061467d565b60008054604051600160a060020a03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600061154461198b565b15156115655760405160e560020a62461bcd0281526004016104ff9061467d565b60005460a060020a900460ff16156115925760405160e560020a62461bcd0281526004016104ff906145dd565b610d2c6120dd565b60008115156115be5760405160e560020a62461bcd0281526004016104ff9061459d565b6115c88583611f49565b15156115e95760405160e560020a62461bcd0281526004016104ff906145bd565b600160a060020a038516600090815260036020908152604080832067ffffffffffffffff8816845282529182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084526060939283018282801561169a5780601f1061166f5761010080835404028352916020019161169a565b820191906000526020600020905b81548152906001019060200180831161167d57829003601f168201915b5050505050905080516000141515156116c85760405160e560020a62461bcd0281526004016104ff906146bd565b6116d0612e9a565b6060604051908101604052808381526020018681526020016116f28987612002565b90529050606061170182612157565b90506000600160009054906101000a9004600160a060020a03169050600081600160a060020a03166387939a7f6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561175b57600080fd5b505afa15801561176f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117939190810190613161565b67ffffffffffffffff8a16600090815260026020818152604092839020805484516001821615610100026000190190911693909304601f8101839004830284018301909452838352939450849360609390918301828280156118365780601f1061180b57610100808354040283529160200191611836565b820191906000526020600020905b81548152906001019060200180831161181957829003601f168201915b5050505050905080516000141515156118645760405160e560020a62461bcd0281526004016104ff9061460d565b6040517fbd5cf625000000000000000000000000000000000000000000000000000000008152600160a060020a0383169063bd5cf625906118ad908e9085908a906004016147fb565b602060405180830381600087803b1580156118c757600080fd5b505af11580156118db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506118ff91908101906135c3565b15156119205760405160e560020a62461bcd0281526004016104ff9061468d565b7f8636abd6d0e464fe725a13346c7ac779b73561c705506044a2e6b2cdb1295ea58c61194a611c20565b8d8a8e8e60405161196096959493929190614427565b60405180910390a160019750505050505050505b949350505050565b600054600160a060020a031690565b60008054600160a060020a03166119a0611c20565b600160a060020a031614905090565b600260208181526000928352604092839020805484516001821615610100026000190190911693909304601f8101839004830284018301909452838352919290830182828015610f185780601f10610eed57610100808354040283529160200191610f18565b611a1d61198b565b1515611a3e5760405160e560020a62461bcd0281526004016104ff9061467d565b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383811691909117918290556040517f43b1a8ec337adb61e8311ed025d99c80db65c02fe5c5027c1b6a93b40970cec492611a9c9216906143bb565b60405180910390a150565b600154600160a060020a031681565b611abe61198b565b1515611adf5760405160e560020a62461bcd0281526004016104ff9061467d565b611ae881612284565b50565b6000805460a060020a900460ff1615611b195760405160e560020a62461bcd0281526004016104ff906145dd565b811515611b3b5760405160e560020a62461bcd0281526004016104ff9061459d565b600160a060020a0380841660009081526004602052604090205416801515611b785760405160e560020a62461bcd0281526004016104ff9061476d565b611b828184611f49565b1515611ba35760405160e560020a62461bcd0281526004016104ff906146fd565b6000611baf8285612002565b90506000611bbd8683611d55565b9050611bca863383611e39565b1515611beb5760405160e560020a62461bcd0281526004016104ff9061452d565b7fcc7320d7ac24f61b5790719a3c0d7c3cdb569d0affd3996fd075136aa97fb51633878584604051610e6894939291906143d7565b3390565b611c2c612e9a565b611c34612e9a565b6000611c408482612317565b9083529050611c4f8482612317565b60208401919091529050611c6384826123d5565b5060408301525092915050565b60008060019050835460026001808316156101000203821604845180821460018114611c9f5760009450611d1a565b8215611d1a576020831060018114611cfd57600189600052602060002060208a018581015b600284828410011415611cf4578151835414611ce35760009950600093505b600183019250602082019150611cc4565b50505050611d18565b610100808604029450602088015185141515611d1857600095505b505b50929695505050505050565b8051600090601414611d4d5760405160e560020a62461bcd0281526004016104ff9061456d565b506014015190565b600080600160a060020a0384161515611d7057506012611de7565b83600160a060020a031663313ce5676040518163ffffffff1660e060020a02815260040160206040518083038186803b158015611dac57600080fd5b505afa158015611dc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611de491908101906136d7565b90505b60ff811660121415611dfc5782915050610b6d565b601260ff82161015611e25578060120360ff16600a0a83811515611e1c57fe5b04915050610b6d565b6012810360ff16600a0a8302915050610b6d565b6000600160a060020a0384161515611e8757604051600160a060020a0384169083156108fc029084906000818181858888f19350505050158015611e81573d6000803e3d6000fd5b50611eb3565b611e9284848461249f565b1515611eb35760405160e560020a62461bcd0281526004016104ff9061457d565b5060019392505050565b60005460a060020a900460ff161515611eeb5760405160e560020a62461bcd0281526004016104ff9061453d565b6000805474ff0000000000000000000000000000000000000000191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa611f32611c20565b604051611f3f91906143c9565b60405180910390a1565b6000600160a060020a0383161515611fa457341515611f7d5760405160e560020a62461bcd0281526004016104ff906147ad565b348214611f9f5760405160e560020a62461bcd0281526004016104ff9061471d565b611ff9565b3415611fc55760405160e560020a62461bcd0281526004016104ff9061465d565b611fd883611fd1611c20565b30856124bc565b1515611ff95760405160e560020a62461bcd0281526004016104ff9061457d565b50600192915050565b600080600160a060020a038416151561201d57506012612094565b83600160a060020a031663313ce5676040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561205957600080fd5b505afa15801561206d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061209191908101906136d7565b90505b60ff8116601214156120a95782915050610b6d565b601260ff821610156120c9578060120360ff16600a0a8302915050610b6d565b6012810360ff16600a0a83811515611e1c57fe5b60005460a060020a900460ff161561210a5760405160e560020a62461bcd0281526004016104ff906145dd565b6000805474ff0000000000000000000000000000000000000000191660a060020a1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611f32611c20565b60608061216783600001516124e6565b61217484602001516124e6565b61218185604001516125ac565b6040516020018084805190602001908083835b602083106121b35780518252601f199092019160209182019101612194565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b602083106121fb5780518252601f1990920191602091820191016121dc565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106122435780518252601f199092019160209182019101612224565b6001836020036101000a0380198251168184511680821785525050505050509050019350505050604051602081830303815290604052905080915050919050565b600160a060020a03811615156122af5760405160e560020a62461bcd0281526004016104ff9061458d565b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60606000806123268585612630565b865190955090915081850111801590612340575080840184105b15156123615760405160e560020a62461bcd0281526004016104ff9061477d565b60608115801561237c576040519150602082016040526123c6565b6040519150601f8316801560200281840101848101888315602002848c0101015b818310156123b557805183526020928301920161239d565b5050848452601f01601f1916604052505b509250830190505b9250929050565b600080835183602001111580156123ee57508260200183105b151561240f5760405160e560020a62461bcd0281526004016104ff9061454d565b600060405160206000600182038760208a0101515b838310156124445780821a83860153600183019250600182039150612424565b50505081016040525190507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156124925760405160e560020a62461bcd0281526004016104ff9061463d565b9460209390930193505050565b6000836114af600160a060020a038216858563ffffffff6127df16565b6000846124da600160a060020a03821686868663ffffffff61288316565b50600195945050505050565b80516060906124f4816128c6565b836040516020018083805190602001908083835b602083106125275780518252601f199092019160209182019101612508565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831061256f5780518252601f199092019160209182019101612550565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052915050919050565b60607f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156125f15760405160e560020a62461bcd0281526004016104ff906146ad565b60405160208082526000601f5b828210156126205785811a8260208601015360019190910190600019016125fe565b5050506040818101905292915050565b600080600061263f8585612a47565b9450905060007ffd00000000000000000000000000000000000000000000000000000000000000600160f860020a0319831614156126c9576126818686612a95565b955061ffff16905060fd811080159061269c575061ffff8111155b15156126bd5760405160e560020a62461bcd0281526004016104ff9061455d565b92508391506123ce9050565b7ffe00000000000000000000000000000000000000000000000000000000000000600160f860020a031983161415612745576127058686612b04565b955063ffffffff16905061ffff81118015612724575063ffffffff8111155b15156126bd5760405160e560020a62461bcd0281526004016104ff906146ed565b600160f860020a03198083161415612795576127618686612b90565b955067ffffffffffffffff16905063ffffffff81116126bd5760405160e560020a62461bcd0281526004016104ff906146ed565b5060ff7f010000000000000000000000000000000000000000000000000000000000000082041660fd81106126bd5760405160e560020a62461bcd0281526004016104ff906146ed565b60405161287e9084907fa9059cbb000000000000000000000000000000000000000000000000000000009061281a90869086906024016144b7565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612c1c565b505050565b6040516128c09085907f23b872dd000000000000000000000000000000000000000000000000000000009061281a9087908790879060240161448f565b50505050565b606060fd8267ffffffffffffffff1610156128eb576128e482612d51565b9050611138565b61ffff67ffffffffffffffff8316116129e6576129277ffd00000000000000000000000000000000000000000000000000000000000000612d6d565b61293083612d9a565b6040516020018083805190602001908083835b602083106129625780518252601f199092019160209182019101612943565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106129aa5780518252601f19909201916020918201910161298b565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529050611138565b63ffffffff67ffffffffffffffff831611612a2d57612a247ffe00000000000000000000000000000000000000000000000000000000000000612d6d565b61293083612ddd565b612a3e600160f860020a0319612d6d565b61293083612e20565b60008083518360010111158015612a6057508260010183105b1515612a815760405160e560020a62461bcd0281526004016104ff9061469d565b505081810160200151600182019250929050565b60008083518360020111158015612aae57508260020183105b1515612acf5760405160e560020a62461bcd0281526004016104ff9061472d565b6000604051846020870101518060011a82538060001a6001830153506002818101604052601d19909101519694019450505050565b60008083518360040111158015612b1d57508260040183105b1515612b3e5760405160e560020a62461bcd0281526004016104ff9061475d565b600060405160046000600182038760208a0101515b83831015612b735780821a83860153600183019250600182039150612b53565b505050808201604052602003900351956004949094019450505050565b60008083518360080111158015612ba957508260080183105b1515612bca5760405160e560020a62461bcd0281526004016104ff9061474d565b600060405160086000600182038760208a0101515b83831015612bff5780821a83860153600183019250600182039150612bdf565b505050808201604052602003900351956008949094019450505050565b612c2582612e63565b1515612c465760405160e560020a62461bcd0281526004016104ff9061479d565b6000606083600160a060020a0316836040518082805190602001908083835b60208310612c845780518252601f199092019160209182019101612c65565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612ce6576040519150601f19603f3d011682016040523d82523d6000602084013e612ceb565b606091505b5091509150811515612d125760405160e560020a62461bcd0281526004016104ff906145ad565b6000815111156128c05780806020019051612d3091908101906135c3565b15156128c05760405160e560020a62461bcd0281526004016104ff9061473d565b604080516001815260f89290921b602083015260218201905290565b6060610b6d7f01000000000000000000000000000000000000000000000000000000000000008304612d51565b6040516002808252606091906000601f5b82821015612dcd5785811a826020860101536001919091019060001901612dab565b5050506022810160405292915050565b6040516004808252606091906000601f5b82821015612e105785811a826020860101536001919091019060001901612dee565b5050506024810160405292915050565b6040516008808252606091906000601f5b82821015612e535785811a826020860101536001919091019060001901612e31565b5050506028810160405292915050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081158015906119745750141592915050565b6060604051908101604052806060815260200160608152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612efd57805160ff1916838001178555612f2a565b82800160010185558215612f2a579182015b82811115612f2a578251825591602001919060010190612f0f565b50612f36929150612f3a565b5090565b610d3091905b80821115612f365760008155600101612f40565b6000610c1182356148b6565b6000610c1182516148b6565b6000601f82018313612f7d57600080fd5b8135612f90612f8b82614869565b614842565b91508181835260208401935060208101905083856020840282011115612fb557600080fd5b60005b83811015612fe15781612fcb8882612f54565b8452506020928301929190910190600101612fb8565b5050505092915050565b6000601f82018313612ffc57600080fd5b813561300a612f8b82614869565b81815260209384019390925082018360005b83811015612fe1578135860161303288826130c4565b845250602092830192919091019060010161301c565b6000601f8201831361305957600080fd5b8135613067612f8b82614869565b9150818183526020840193506020810190508385602084028201111561308c57600080fd5b60005b83811015612fe157816130a2888261312b565b845250602092830192919091019060010161308f565b6000610c1182516148c1565b6000601f820183136130d557600080fd5b81356130e3612f8b8261488a565b915080825260208301602083018583830111156130ff57600080fd5b61310a8382846148f6565b50505092915050565b6000610c118235610d30565b6000610c118251610d30565b6000610c1182356148d2565b6000610c1182516148df565b60006020828403121561315557600080fd5b60006119748484612f54565b60006020828403121561317357600080fd5b60006119748484612f60565b6000806040838503121561319257600080fd5b600061319e8585612f54565b92505060206131af85828601612f54565b9150509250929050565b600080600080600060a086880312156131d157600080fd5b60006131dd8888612f54565b95505060206131ee88828901612f54565b94505060406131ff8882890161312b565b935050606086013567ffffffffffffffff81111561321c57600080fd5b613228888289016130c4565b925050608086013567ffffffffffffffff81111561324557600080fd5b613251888289016130c4565b9150509295509295909350565b6000806040838503121561327157600080fd5b600061327d8585612f54565b92505060206131af85828601613113565b600080604083850312156132a157600080fd5b60006132ad8585612f54565b92505060206131af8582860161312b565b6000806000606084860312156132d357600080fd5b60006132df8686612f54565b93505060206132f08682870161312b565b925050604084013567ffffffffffffffff81111561330d57600080fd5b613319868287016130c4565b9150509250925092565b6000806000806080858703121561333957600080fd5b60006133458787612f54565b94505060206133568782880161312b565b935050604085013567ffffffffffffffff81111561337357600080fd5b61337f878288016130c4565b925050606061339087828801613113565b91505092959194509250565b600080604083850312156133af57600080fd5b823567ffffffffffffffff8111156133c657600080fd5b6133d285828601612f6c565b925050602083013567ffffffffffffffff8111156133ef57600080fd5b6131af85828601612f6c565b600080600080600060a0868803121561341357600080fd5b853567ffffffffffffffff81111561342a57600080fd5b61343688828901612f6c565b955050602086013567ffffffffffffffff81111561345357600080fd5b61345f88828901612f6c565b945050604086013567ffffffffffffffff81111561347c57600080fd5b61348888828901613048565b935050606086013567ffffffffffffffff8111156134a557600080fd5b6134b188828901612feb565b925050608086013567ffffffffffffffff8111156134ce57600080fd5b61325188828901612feb565b6000806000606084860312156134ef57600080fd5b833567ffffffffffffffff81111561350657600080fd5b61351286828701612f6c565b935050602084013567ffffffffffffffff81111561352f57600080fd5b61353b86828701613048565b925050604084013567ffffffffffffffff81111561355857600080fd5b61331986828701612feb565b6000806040838503121561357757600080fd5b823567ffffffffffffffff81111561358e57600080fd5b61359a85828601613048565b925050602083013567ffffffffffffffff8111156135b757600080fd5b6131af85828601612feb565b6000602082840312156135d557600080fd5b600061197484846130b8565b6000806000606084860312156135f657600080fd5b833567ffffffffffffffff81111561360d57600080fd5b613619868287016130c4565b935050602084013567ffffffffffffffff81111561363657600080fd5b613642868287016130c4565b92505060406133198682870161312b565b60006020828403121561366557600080fd5b6000611974848461311f565b60006020828403121561368357600080fd5b6000611974848461312b565b600080604083850312156136a257600080fd5b60006136ae858561312b565b925050602083013567ffffffffffffffff8111156136cb57600080fd5b6131af858286016130c4565b6000602082840312156136e957600080fd5b60006119748484613137565b6136fe816148e5565b82525050565b6136fe816148b6565b6136fe816148c1565b6000613721826148b2565b808452613735816020860160208601614902565b61373e8161492e565b9093016020019392505050565b603e81527f7472616e736665722061737365742066726f6d206c6f636b5f70726f7879206360208201527f6f6e747261637420746f2066726f6d41646472657373206661696c6564210000604082015260600190565b601481527f5061757361626c653a206e6f7420706175736564000000000000000000000000602082015260400190565b602381527f4e65787455696e743235352c206f66667365742065786365656473206d61786960208201527f6d756d0000000000000000000000000000000000000000000000000000000000604082015260600190565b601f81527f4e65787455696e7431362c2076616c7565206f7574736964652072616e676500602082015260400190565b602381527f6279746573206c656e67746820646f6573206e6f74206d61746368206164647260208201527f6573730000000000000000000000000000000000000000000000000000000000604082015260600190565b603381527f7472616e7366657220657263323020617373657420746f206c6f636b5f70726f60208201527f787920636f6e7472616374206661696c65642100000000000000000000000000604082015260600190565b602681527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160208201527f6464726573730000000000000000000000000000000000000000000000000000604082015260600190565b601681527f616d6f756e742063616e6e6f74206265207a65726f2100000000000000000000602082015260400190565b60208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260400190565b603e81527f7472616e736665722061737365742066726f6d2066726f6d416464726573732060208201527f746f206c6f636b5f70726f787920636f6e7472616374206661696c6564210000604082015260600190565b601b81527f746f4173736574486173682063616e6e6f7420626520656d7074790000000000602082015260400190565b601081527f5061757361626c653a2070617573656400000000000000000000000000000000602082015260400190565b602281527f646f206e6f7420737570706f7274206465706f73697465207468697320746f6b60208201527f656e000000000000000000000000000000000000000000000000000000000000604082015260600190565b603c81527f7472616e736665722061737365742066726f6d206c6f636b5f70726f7879206360208201527f6f6e747261637420746f20746f41646472657373206661696c65642100000000604082015260600190565b601981527f656d70747920696c6c6567616c20746f50726f78794861736800000000000000602082015260400190565b602581527f62696e644c50416e64417373657442617463683a2061726773206c656e67746860208201527f2064696666000000000000000000000000000000000000000000000000000000604082015260600190565b602d81527f6d736753656e646572206973206e6f742045746843726f7373436861696e4d6160208201527f6e61676572436f6e747261637400000000000000000000000000000000000000604082015260600190565b601781527f56616c75652065786365656473207468652072616e6765000000000000000000602082015260400190565b602b81527f66726f6d2070726f787920636f6e747261637420616464726573732063616e6e60208201527f6f7420626520656d707479000000000000000000000000000000000000000000604082015260600190565b602281527f74686572652073686f756c64206265206e6f206574686572207472616e73666560208201527f7221000000000000000000000000000000000000000000000000000000000000604082015260600190565b602481527f62696e6450726f78794861736842617463683a2061726773206c656e6774682060208201527f6469666600000000000000000000000000000000000000000000000000000000604082015260600190565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65729082015260400190565b602f81527f45746843726f7373436861696e4d616e616765722063726f7373436861696e2060208201527f6578656375746564206572726f72210000000000000000000000000000000000604082015260600190565b60208082527f4e657874427974652c204f66667365742065786365656473206d6178696d756d9082015260400190565b600681527f756e6c6f636b0000000000000000000000000000000000000000000000000000602082015260400190565b601b81527f56616c756520657863656564732075696e743235352072616e67650000000000602082015260400190565b601981527f656d70747920696c6c6567616c20746f41737365744861736800000000000000602082015260400190565b601981527f746f416464726573732063616e6e6f7420626520656d70747900000000000000602082015260400190565b604b81527f7472616e736665722070726f6f66206f66206c69717569646974792066726f6d60208201527f206c6f636b5f70726f787920636f6e747261637420746f2066726f6d4164647260408201527f657373206661696c656421000000000000000000000000000000000000000000606082015260800190565b60208082527f4e65787456617255696e742c2076616c7565206f7574736964652072616e67659082015260400190565b604b81527f7472616e736665722070726f6f66206f66206c69717569646974792066726f6d60208201527f2066726f6d4164647265737320746f206c6f636b5f70726f787920636f6e747260408201527f616374206661696c656421000000000000000000000000000000000000000000606082015260800190565b602481527f62696e6441737365744861736842617463683a2061726773206c656e6774682060208201527f6469666600000000000000000000000000000000000000000000000000000000604082015260600190565b602981527f7472616e73666572726564206574686572206973206e6f7420657175616c207460208201527f6f20616d6f756e74210000000000000000000000000000000000000000000000604082015260600190565b602281527f4e65787455696e7431362c206f66667365742065786365656473206d6178696d60208201527f756d000000000000000000000000000000000000000000000000000000000000604082015260600190565b602a81527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60208201527f6f74207375636365656400000000000000000000000000000000000000000000604082015260600190565b602281527f4e65787455696e7436342c206f66667365742065786365656473206d6178696d60208201527f756d000000000000000000000000000000000000000000000000000000000000604082015260600190565b602281527f4e65787455696e7433322c206f66667365742065786365656473206d6178696d60208201527f756d000000000000000000000000000000000000000000000000000000000000604082015260600190565b602281527f646f206e6f7420737570706f7274207769746864726177207468697320746f6b60208201527f656e000000000000000000000000000000000000000000000000000000000000604082015260600190565b602481527f4e65787456617242797465732c206f66667365742065786365656473206d617860208201527f696d756d00000000000000000000000000000000000000000000000000000000604082015260600190565b602281527f46726f6d2050726f787920636f6e74726163742061646472657373206572726f60208201527f7221000000000000000000000000000000000000000000000000000000000000604082015260600190565b601f81527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400602082015260400190565b602181527f7472616e736665727265642065746865722063616e6e6f74206265207a65726f60208201527f2100000000000000000000000000000000000000000000000000000000000000604082015260600190565b602481527f62696e644c50546f417373657442617463683a2061726773206c656e6774682060208201527f6469666600000000000000000000000000000000000000000000000000000000604082015260600190565b6136fe81610d30565b6136fe816148d2565b60208101610b6d8284613704565b60208101610b6d82846136f5565b608081016143e582876136f5565b6143f26020830186613704565b6143ff6040830185613704565b610a2a60608301846143a9565b6040810161441a8285613704565b610c116020830184613704565b60c081016144358289613704565b61444260208301886136f5565b61444f60408301876143b2565b81810360608301526144618186613716565b905081810360808301526144758185613716565b905061448460a08301846143a9565b979650505050505050565b6060810161449d8286613704565b6144aa6020830185613704565b61197460408301846143a9565b604081016144c58285613704565b610c1160208301846143a9565b608081016144e08287613704565b6144ed60208301866143b2565b81810360408301526144ff8185613716565b9050610a2a60608301846143a9565b60208101610b6d828461370d565b60208082528101610c118184613716565b60208082528101610b6d8161374b565b60208082528101610b6d816137a1565b60208082528101610b6d816137d1565b60208082528101610b6d81613827565b60208082528101610b6d81613857565b60208082528101610b6d816138ad565b60208082528101610b6d81613903565b60208082528101610b6d81613959565b60208082528101610b6d81613989565b60208082528101610b6d816139b9565b60208082528101610b6d81613a0f565b60208082528101610b6d81613a3f565b60208082528101610b6d81613a6f565b60208082528101610b6d81613ac5565b60208082528101610b6d81613b1b565b60208082528101610b6d81613b4b565b60208082528101610b6d81613ba1565b60208082528101610b6d81613bf7565b60208082528101610b6d81613c27565b60208082528101610b6d81613c7d565b60208082528101610b6d81613cd3565b60208082528101610b6d81613d29565b60208082528101610b6d81613d59565b60208082528101610b6d81613daf565b60208082528101610b6d81613e0f565b60208082528101610b6d81613e3f565b60208082528101610b6d81613e6f565b60208082528101610b6d81613e9f565b60208082528101610b6d81613f1b565b60208082528101610b6d81613f4b565b60208082528101610b6d81613fc7565b60208082528101610b6d8161401d565b60208082528101610b6d81614073565b60208082528101610b6d816140c9565b60208082528101610b6d8161411f565b60208082528101610b6d81614175565b60208082528101610b6d816141cb565b60208082528101610b6d81614221565b60208082528101610b6d81614277565b60208082528101610b6d816142cd565b60208082528101610b6d816142fd565b60208082528101610b6d81614353565b60208101610b6d82846143a9565b604081016147e982856143b2565b81810360208301526119748184613716565b6080810161480982866143b2565b818103602083015261481b8185613716565b9050818103604083015261482e81613ddf565b90508181036060830152610a2a8184613716565b60405181810167ffffffffffffffff8111828210171561486157600080fd5b604052919050565b600067ffffffffffffffff82111561488057600080fd5b5060209081020190565b600067ffffffffffffffff8211156148a157600080fd5b506020601f91909101601f19160190565b5190565b6000610b6d826148c6565b151590565b600160a060020a031690565b67ffffffffffffffff1690565b60ff1690565b6000610b6d826000610b6d826148b6565b82818337506000910152565b60005b8381101561491d578181015183820152602001614905565b838111156128c05750506000910152565b601f01601f19169056fe2319c5345cde8ceb76a957b55d75082616215452400c34305e4e6adaaf42f7111628c8374c1bdfeb2275fd9f4c90562fd3fae974783dc522c8234e36abcfc58ea265627a7a7230582020e650bbca43da1a3f03f61b6e4460b77b50ae1c6d0bf83e2d2b0d5522f0cac36c6578706572696d656e74616cf50037
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.