Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Deposit ERC20 | 16493601 | 1119 days ago | IN | 0 ETH | 0.00101693 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
DepositManager
Compiler Version
v0.5.11+commit.c082d0b4
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2020-06-04
*/
/**
Matic network contracts
*/
pragma solidity ^0.5.2;
contract IERC721Receiver {
/**
* @notice Handle the receipt of an NFT
* @dev The ERC721 smart contract calls this function on the recipient
* after a `safeTransfer`. This function MUST return the function selector,
* otherwise the caller will revert the transaction. The selector to be
* returned can be obtained as `this.onERC721Received.selector`. This
* function MAY throw to revert and reject the transfer.
* Note: the ERC721 contract address is always the message sender.
* @param operator The address which called `safeTransferFrom` function
* @param from The address which previously owned the token
* @param tokenId The NFT identifier which is being transferred
* @param data Additional data with no specified format
* @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
public returns (bytes4);
}
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @title IERC165
* @dev https://eips.ethereum.org/EIPS/eip-165
*/
interface IERC165 {
/**
* @notice Query if a contract implements an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @dev Interface identification is specified in ERC-165. This function
* uses less than 30,000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
contract IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) public view returns (uint256 balance);
function ownerOf(uint256 tokenId) public view returns (address owner);
function approve(address to, uint256 tokenId) public;
function getApproved(uint256 tokenId) public view returns (address operator);
function setApprovalForAll(address operator, bool _approved) public;
function isApprovedForAll(address owner, address operator) public view returns (bool);
function transferFrom(address from, address to, uint256 tokenId) public;
function safeTransferFrom(address from, address to, uint256 tokenId) public;
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}
library SafeMath {
/**
* @dev Multiplies two unsigned integers, reverts on 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-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
contract ContractReceiver {
/// @dev Function that is called when a user or another contract wants to transfer funds.
/// @param _from Transaction initiator, analogue of msg.sender
/// @param _value Number of tokens to transfer.
/// @param _data Data containig a function signature and/or parameters
function tokenFallback(address _from, uint256 _value, bytes memory _data)
public;
}
interface IGovernance {
function update(address target, bytes calldata data) external;
}
contract Governable {
IGovernance public governance;
constructor(address _governance) public {
governance = IGovernance(_governance);
}
modifier onlyGovernance() {
require(
msg.sender == address(governance),
"Only governance contract is authorized"
);
_;
}
}
contract IWithdrawManager {
function createExitQueue(address token) external;
function verifyInclusion(
bytes calldata data,
uint8 offset,
bool verifyTxInclusion
) external view returns (uint256 age);
function addExitToQueue(
address exitor,
address childToken,
address rootToken,
uint256 exitAmountOrTokenId,
bytes32 txHash,
bool isRegularExit,
uint256 priority
) external;
function addInput(
uint256 exitId,
uint256 age,
address utxoOwner,
address token
) external;
function challengeExit(
uint256 exitId,
uint256 inputId,
bytes calldata challengeData,
address adjudicatorPredicate
) external;
}
contract Registry is Governable {
// @todo hardcode constants
bytes32 private constant WETH_TOKEN = keccak256("wethToken");
bytes32 private constant DEPOSIT_MANAGER = keccak256("depositManager");
bytes32 private constant STAKE_MANAGER = keccak256("stakeManager");
bytes32 private constant VALIDATOR_SHARE = keccak256("validatorShare");
bytes32 private constant WITHDRAW_MANAGER = keccak256("withdrawManager");
bytes32 private constant CHILD_CHAIN = keccak256("childChain");
bytes32 private constant STATE_SENDER = keccak256("stateSender");
bytes32 private constant SLASHING_MANAGER = keccak256("slashingManager");
address public erc20Predicate;
address public erc721Predicate;
mapping(bytes32 => address) public contractMap;
mapping(address => address) public rootToChildToken;
mapping(address => address) public childToRootToken;
mapping(address => bool) public proofValidatorContracts;
mapping(address => bool) public isERC721;
enum Type {Invalid, ERC20, ERC721, Custom}
struct Predicate {
Type _type;
}
mapping(address => Predicate) public predicates;
event TokenMapped(address indexed rootToken, address indexed childToken);
event ProofValidatorAdded(address indexed validator, address indexed from);
event ProofValidatorRemoved(address indexed validator, address indexed from);
event PredicateAdded(address indexed predicate, address indexed from);
event PredicateRemoved(address indexed predicate, address indexed from);
event ContractMapUpdated(bytes32 indexed key, address indexed previousContract, address indexed newContract);
constructor(address _governance) public Governable(_governance) {}
function updateContractMap(bytes32 _key, address _address) external onlyGovernance {
emit ContractMapUpdated(_key, contractMap[_key], _address);
contractMap[_key] = _address;
}
/**
* @dev Map root token to child token
* @param _rootToken Token address on the root chain
* @param _childToken Token address on the child chain
* @param _isERC721 Is the token being mapped ERC721
*/
function mapToken(
address _rootToken,
address _childToken,
bool _isERC721
) external onlyGovernance {
require(_rootToken != address(0x0) && _childToken != address(0x0), "INVALID_TOKEN_ADDRESS");
rootToChildToken[_rootToken] = _childToken;
childToRootToken[_childToken] = _rootToken;
isERC721[_rootToken] = _isERC721;
IWithdrawManager(contractMap[WITHDRAW_MANAGER]).createExitQueue(_rootToken);
emit TokenMapped(_rootToken, _childToken);
}
function addErc20Predicate(address predicate) public onlyGovernance {
require(predicate != address(0x0), "Can not add null address as predicate");
erc20Predicate = predicate;
addPredicate(predicate, Type.ERC20);
}
function addErc721Predicate(address predicate) public onlyGovernance {
erc721Predicate = predicate;
addPredicate(predicate, Type.ERC721);
}
function addPredicate(address predicate, Type _type) public onlyGovernance {
require(predicates[predicate]._type == Type.Invalid, "Predicate already added");
predicates[predicate]._type = _type;
emit PredicateAdded(predicate, msg.sender);
}
function removePredicate(address predicate) public onlyGovernance {
require(predicates[predicate]._type != Type.Invalid, "Predicate does not exist");
delete predicates[predicate];
emit PredicateRemoved(predicate, msg.sender);
}
function getValidatorShareAddress() public view returns (address) {
return contractMap[VALIDATOR_SHARE];
}
function getWethTokenAddress() public view returns (address) {
return contractMap[WETH_TOKEN];
}
function getDepositManagerAddress() public view returns (address) {
return contractMap[DEPOSIT_MANAGER];
}
function getStakeManagerAddress() public view returns (address) {
return contractMap[STAKE_MANAGER];
}
function getSlashingManagerAddress() public view returns (address) {
return contractMap[SLASHING_MANAGER];
}
function getWithdrawManagerAddress() public view returns (address) {
return contractMap[WITHDRAW_MANAGER];
}
function getChildChainAndStateSender() public view returns (address, address) {
return (contractMap[CHILD_CHAIN], contractMap[STATE_SENDER]);
}
function isTokenMapped(address _token) public view returns (bool) {
return rootToChildToken[_token] != address(0x0);
}
function isTokenMappedAndIsErc721(address _token) public view returns (bool) {
require(isTokenMapped(_token), "TOKEN_NOT_MAPPED");
return isERC721[_token];
}
function isTokenMappedAndGetPredicate(address _token) public view returns (address) {
if (isTokenMappedAndIsErc721(_token)) {
return erc721Predicate;
}
return erc20Predicate;
}
function isChildTokenErc721(address childToken) public view returns (bool) {
address rootToken = childToRootToken[childToken];
require(rootToken != address(0x0), "Child token is not mapped");
return isERC721[rootToken];
}
}
/**
* @title ERC20 interface
* @dev see https://eips.ethereum.org/EIPS/eip-20
*/
/**
* @title SafeMath
* @dev Unsigned math operations with safety checks that revert on error
*/
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* https://eips.ethereum.org/EIPS/eip-20
* Originally based on code by FirstBlood:
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*
* This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
* all accounts just by listening to said events. Note that this isn't required by the specification, and other
* compliant implementations may not do it.
*/
contract ERC20 is IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowed;
uint256 private _totalSupply;
/**
* @dev Total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev Gets the balance of the specified address.
* @param owner The address to query the balance of.
* @return A uint256 representing the amount owned by the passed address.
*/
function balanceOf(address owner) public view returns (uint256) {
return _balances[owner];
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param owner address The address which owns the funds.
* @param spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address owner, address spender) public view returns (uint256) {
return _allowed[owner][spender];
}
/**
* @dev Transfer token to a specified address
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function transfer(address to, uint256 value) public returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* 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
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function approve(address spender, uint256 value) public returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
/**
* @dev Transfer tokens from one address to another.
* Note that while this function emits an Approval event, this is not required as per the specification,
* and other compliant implementations may not emit the event.
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 the amount of tokens to be transferred
*/
function transferFrom(address from, address to, uint256 value) public returns (bool) {
_transfer(from, to, value);
_approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
return true;
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
return true;
}
/**
* @dev Transfer token for a specified addresses
* @param from The address to transfer from.
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function _transfer(address from, address to, uint256 value) internal {
require(to != address(0));
_balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value);
emit Transfer(from, to, value);
}
/**
* @dev Internal function that mints an amount of the token and assigns it to
* an account. This encapsulates the modification of balances such that the
* proper events are emitted.
* @param account The account that will receive the created tokens.
* @param value The amount that will be created.
*/
function _mint(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value);
emit Transfer(address(0), account, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account.
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burn(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
emit Transfer(account, address(0), value);
}
/**
* @dev Approve an address to spend another addresses' tokens.
* @param owner The address that owns the tokens.
* @param spender The address that will spend the tokens.
* @param value The number of tokens that can be spent.
*/
function _approve(address owner, address spender, uint256 value) internal {
require(spender != address(0));
require(owner != address(0));
_allowed[owner][spender] = value;
emit Approval(owner, spender, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account, deducting from the sender's allowance for said account. Uses the
* internal burn function.
* Emits an Approval event (reflecting the reduced allowance).
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burnFrom(address account, uint256 value) internal {
_burn(account, value);
_approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
}
}
contract WETH is ERC20 {
event Deposit(address indexed dst, uint256 wad);
event Withdrawal(address indexed src, uint256 wad);
function deposit() public payable;
function withdraw(uint256 wad) public;
function withdraw(uint256 wad, address user) public;
}
interface IDepositManager {
function depositEther() external payable;
function transferAssets(
address _token,
address _user,
uint256 _amountOrNFTId
) external;
function depositERC20(address _token, uint256 _amount) external;
function depositERC721(address _token, uint256 _tokenId) external;
}
library RLPReader {
uint8 constant STRING_SHORT_START = 0x80;
uint8 constant STRING_LONG_START = 0xb8;
uint8 constant LIST_SHORT_START = 0xc0;
uint8 constant LIST_LONG_START = 0xf8;
uint8 constant WORD_SIZE = 32;
struct RLPItem {
uint len;
uint memPtr;
}
struct Iterator {
RLPItem item; // Item that's being iterated over.
uint nextPtr; // Position of the next item in the list.
}
/*
* @dev Returns the next element in the iteration. Reverts if it has not next element.
* @param self The iterator.
* @return The next element in the iteration.
*/
function next(Iterator memory self) internal pure returns (RLPItem memory) {
require(hasNext(self));
uint ptr = self.nextPtr;
uint itemLength = _itemLength(ptr);
self.nextPtr = ptr + itemLength;
return RLPItem(itemLength, ptr);
}
/*
* @dev Returns true if the iteration has more elements.
* @param self The iterator.
* @return true if the iteration has more elements.
*/
function hasNext(Iterator memory self) internal pure returns (bool) {
RLPItem memory item = self.item;
return self.nextPtr < item.memPtr + item.len;
}
/*
* @param item RLP encoded bytes
*/
function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {
uint memPtr;
assembly {
memPtr := add(item, 0x20)
}
return RLPItem(item.length, memPtr);
}
/*
* @dev Create an iterator. Reverts if item is not a list.
* @param self The RLP item.
* @return An 'Iterator' over the item.
*/
function iterator(RLPItem memory self) internal pure returns (Iterator memory) {
require(isList(self));
uint ptr = self.memPtr + _payloadOffset(self.memPtr);
return Iterator(self, ptr);
}
/*
* @param item RLP encoded bytes
*/
function rlpLen(RLPItem memory item) internal pure returns (uint) {
return item.len;
}
/*
* @param item RLP encoded bytes
*/
function payloadLen(RLPItem memory item) internal pure returns (uint) {
return item.len - _payloadOffset(item.memPtr);
}
/*
* @param item RLP encoded list in bytes
*/
function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {
require(isList(item));
uint items = numItems(item);
RLPItem[] memory result = new RLPItem[](items);
uint memPtr = item.memPtr + _payloadOffset(item.memPtr);
uint dataLen;
for (uint i = 0; i < items; i++) {
dataLen = _itemLength(memPtr);
result[i] = RLPItem(dataLen, memPtr);
memPtr = memPtr + dataLen;
}
return result;
}
// @return indicator whether encoded payload is a list. negate this function call for isData.
function isList(RLPItem memory item) internal pure returns (bool) {
if (item.len == 0) return false;
uint8 byte0;
uint memPtr = item.memPtr;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < LIST_SHORT_START)
return false;
return true;
}
/** RLPItem conversions into data types **/
// @returns raw rlp encoding in bytes
function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {
bytes memory result = new bytes(item.len);
if (result.length == 0) return result;
uint ptr;
assembly {
ptr := add(0x20, result)
}
copy(item.memPtr, ptr, item.len);
return result;
}
// any non-zero byte is considered true
function toBoolean(RLPItem memory item) internal pure returns (bool) {
require(item.len == 1);
uint result;
uint memPtr = item.memPtr;
assembly {
result := byte(0, mload(memPtr))
}
return result == 0 ? false : true;
}
function toAddress(RLPItem memory item) internal pure returns (address) {
// 1 byte for the length prefix
require(item.len == 21);
return address(toUint(item));
}
function toUint(RLPItem memory item) internal pure returns (uint) {
require(item.len > 0 && item.len <= 33);
uint offset = _payloadOffset(item.memPtr);
uint len = item.len - offset;
uint result;
uint memPtr = item.memPtr + offset;
assembly {
result := mload(memPtr)
// shfit to the correct location if neccesary
if lt(len, 32) {
result := div(result, exp(256, sub(32, len)))
}
}
return result;
}
// enforces 32 byte length
function toUintStrict(RLPItem memory item) internal pure returns (uint) {
// one byte prefix
require(item.len == 33);
uint result;
uint memPtr = item.memPtr + 1;
assembly {
result := mload(memPtr)
}
return result;
}
function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
require(item.len > 0);
uint offset = _payloadOffset(item.memPtr);
uint len = item.len - offset; // data length
bytes memory result = new bytes(len);
uint destPtr;
assembly {
destPtr := add(0x20, result)
}
copy(item.memPtr + offset, destPtr, len);
return result;
}
/*
* Private Helpers
*/
// @return number of payload items inside an encoded list.
function numItems(RLPItem memory item) private pure returns (uint) {
if (item.len == 0) return 0;
uint count = 0;
uint currPtr = item.memPtr + _payloadOffset(item.memPtr);
uint endPtr = item.memPtr + item.len;
while (currPtr < endPtr) {
currPtr = currPtr + _itemLength(currPtr); // skip over an item
count++;
}
return count;
}
// @return entire rlp item byte length
function _itemLength(uint memPtr) private pure returns (uint) {
uint itemLen;
uint byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START)
itemLen = 1;
else if (byte0 < STRING_LONG_START)
itemLen = byte0 - STRING_SHORT_START + 1;
else if (byte0 < LIST_SHORT_START) {
assembly {
let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is
memPtr := add(memPtr, 1) // skip over the first byte
/* 32 byte word size */
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
itemLen := add(dataLen, add(byteLen, 1))
}
}
else if (byte0 < LIST_LONG_START) {
itemLen = byte0 - LIST_SHORT_START + 1;
}
else {
assembly {
let byteLen := sub(byte0, 0xf7)
memPtr := add(memPtr, 1)
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
itemLen := add(dataLen, add(byteLen, 1))
}
}
return itemLen;
}
// @return number of bytes until the data
function _payloadOffset(uint memPtr) private pure returns (uint) {
uint byte0;
assembly {
byte0 := byte(0, mload(memPtr))
}
if (byte0 < STRING_SHORT_START)
return 0;
else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START))
return 1;
else if (byte0 < LIST_SHORT_START) // being explicit
return byte0 - (STRING_LONG_START - 1) + 1;
else
return byte0 - (LIST_LONG_START - 1) + 1;
}
/*
* @param src Pointer to source
* @param dest Pointer to destination
* @param len Amount of memory to copy from the source
*/
function copy(uint src, uint dest, uint len) private pure {
if (len == 0) return;
// copy as many word sizes as possible
for (; len >= WORD_SIZE; len -= WORD_SIZE) {
assembly {
mstore(dest, mload(src))
}
src += WORD_SIZE;
dest += WORD_SIZE;
}
// left over bytes. Mask is used to remove unwanted bytes from the word
uint mask = 256 ** (WORD_SIZE - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask)) // zero out src
let destpart := and(mload(dest), mask) // retrieve the bytes
mstore(dest, or(destpart, srcpart))
}
}
}
contract Ownable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor () internal {
_owner = msg.sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @return the address of the owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner());
_;
}
/**
* @return true if `msg.sender` is the owner of the contract.
*/
function isOwner() public view returns (bool) {
return msg.sender == _owner;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
* @notice 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 Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0));
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
contract ProxyStorage is Ownable {
address internal proxyTo;
}
contract ChainIdMixin {
bytes constant public networkId = hex"3A99";
uint256 constant public CHAINID = 15001;
}
contract RootChainHeader {
event NewHeaderBlock(
address indexed proposer,
uint256 indexed headerBlockId,
uint256 indexed reward,
uint256 start,
uint256 end,
bytes32 root
);
// housekeeping event
event ResetHeaderBlock(address indexed proposer, uint256 indexed headerBlockId);
struct HeaderBlock {
bytes32 root;
uint256 start;
uint256 end;
uint256 createdAt;
address proposer;
}
}
contract RootChainStorage is ProxyStorage, RootChainHeader, ChainIdMixin {
bytes32 public heimdallId;
uint8 public constant VOTE_TYPE = 2;
uint16 internal constant MAX_DEPOSITS = 10000;
uint256 public _nextHeaderBlock = MAX_DEPOSITS;
uint256 internal _blockDepositId = 1;
mapping(uint256 => HeaderBlock) public headerBlocks;
Registry internal registry;
}
contract IStakeManager {
// validator replacement
function startAuction(uint256 validatorId, uint256 amount) external;
function confirmAuctionBid(
uint256 validatorId,
uint256 heimdallFee,
bool acceptDelegation,
bytes calldata signerPubkey
) external;
function transferFunds(
uint256 validatorId,
uint256 amount,
address delegator
) external returns (bool);
function delegationDeposit(
uint256 validatorId,
uint256 amount,
address delegator
) external returns (bool);
function stake(
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes calldata signerPubkey
) external;
function unstake(uint256 validatorId) external;
function totalStakedFor(address addr) external view returns (uint256);
function supportsHistory() external pure returns (bool);
function stakeFor(
address user,
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes memory signerPubkey
) public;
function checkSignatures(
uint256 blockInterval,
bytes32 voteHash,
bytes32 stateRoot,
address proposer,
bytes memory sigs
) public returns (uint256);
function updateValidatorState(uint256 validatorId, int256 amount) public;
function ownerOf(uint256 tokenId) public view returns (address);
function slash(bytes memory slashingInfoList) public returns (uint256);
function validatorStake(uint256 validatorId) public view returns (uint256);
function epoch() public view returns (uint256);
function withdrawalDelay() public view returns (uint256);
}
interface IRootChain {
function slash() external;
function submitHeaderBlock(bytes calldata data, bytes calldata sigs)
external;
function getLastChildBlock() external view returns (uint256);
function currentHeaderBlock() external view returns (uint256);
}
contract RootChain is RootChainStorage, IRootChain {
using SafeMath for uint256;
using RLPReader for bytes;
using RLPReader for RLPReader.RLPItem;
modifier onlyDepositManager() {
require(msg.sender == registry.getDepositManagerAddress(), "UNAUTHORIZED_DEPOSIT_MANAGER_ONLY");
_;
}
function submitHeaderBlock(bytes calldata data, bytes calldata sigs) external {
(address proposer, uint256 start, uint256 end, bytes32 rootHash, bytes32 accountHash, uint256 _borChainID) = abi
.decode(data, (address, uint256, uint256, bytes32, bytes32, uint256));
require(CHAINID == _borChainID, "Invalid bor chain id");
require(_buildHeaderBlock(proposer, start, end, rootHash), "INCORRECT_HEADER_DATA");
// check if it is better to keep it in local storage instead
IStakeManager stakeManager = IStakeManager(registry.getStakeManagerAddress());
uint256 _reward = stakeManager.checkSignatures(
end.sub(start).add(1),
/**
prefix 01 to data
01 represents positive vote on data and 00 is negative vote
malicious validator can try to send 2/3 on negative vote so 01 is appended
*/
keccak256(abi.encodePacked(bytes(hex"01"), data)),
accountHash,
proposer,
sigs
);
require(_reward != 0, "Invalid checkpoint");
emit NewHeaderBlock(proposer, _nextHeaderBlock, _reward, start, end, rootHash);
_nextHeaderBlock = _nextHeaderBlock.add(MAX_DEPOSITS);
_blockDepositId = 1;
}
function updateDepositId(uint256 numDeposits) external onlyDepositManager returns (uint256 depositId) {
depositId = currentHeaderBlock().add(_blockDepositId);
// deposit ids will be (_blockDepositId, _blockDepositId + 1, .... _blockDepositId + numDeposits - 1)
_blockDepositId = _blockDepositId.add(numDeposits);
require(
// Since _blockDepositId is initialized to 1; only (MAX_DEPOSITS - 1) deposits per header block are allowed
_blockDepositId <= MAX_DEPOSITS,
"TOO_MANY_DEPOSITS"
);
}
function getLastChildBlock() external view returns (uint256) {
return headerBlocks[currentHeaderBlock()].end;
}
function slash() external {
//TODO: future implementation
}
function currentHeaderBlock() public view returns (uint256) {
return _nextHeaderBlock.sub(MAX_DEPOSITS);
}
function _buildHeaderBlock(
address proposer,
uint256 start,
uint256 end,
bytes32 rootHash
) private returns (bool) {
uint256 nextChildBlock;
/*
The ID of the 1st header block is MAX_DEPOSITS.
if _nextHeaderBlock == MAX_DEPOSITS, then the first header block is yet to be submitted, hence nextChildBlock = 0
*/
if (_nextHeaderBlock > MAX_DEPOSITS) {
nextChildBlock = headerBlocks[currentHeaderBlock()].end + 1;
}
if (nextChildBlock != start) {
return false;
}
HeaderBlock memory headerBlock = HeaderBlock({
root: rootHash,
start: nextChildBlock,
end: end,
createdAt: now,
proposer: proposer
});
headerBlocks[_nextHeaderBlock] = headerBlock;
return true;
}
// Housekeeping function. @todo remove later
function setNextHeaderBlock(uint256 _value) public onlyOwner {
require(_value % MAX_DEPOSITS == 0, "Invalid value");
for (uint256 i = _value; i < _nextHeaderBlock; i += MAX_DEPOSITS) {
delete headerBlocks[i];
}
_nextHeaderBlock = _value;
_blockDepositId = 1;
emit ResetHeaderBlock(msg.sender, _nextHeaderBlock);
}
// Housekeeping function. @todo remove later
function setHeimdallId(string memory _heimdallId) public onlyOwner {
heimdallId = keccak256(abi.encodePacked(_heimdallId));
}
}
contract StateSender is Ownable {
using SafeMath for uint256;
uint256 public counter;
mapping(address => address) public registrations;
event NewRegistration(
address indexed user,
address indexed sender,
address indexed receiver
);
event RegistrationUpdated(
address indexed user,
address indexed sender,
address indexed receiver
);
event StateSynced(
uint256 indexed id,
address indexed contractAddress,
bytes data
);
modifier onlyRegistered(address receiver) {
require(registrations[receiver] == msg.sender, "Invalid sender");
_;
}
function syncState(address receiver, bytes calldata data)
external
onlyRegistered(receiver)
{
counter = counter.add(1);
emit StateSynced(counter, receiver, data);
}
// register new contract for state sync
function register(address sender, address receiver) public {
require(
isOwner() || registrations[receiver] == msg.sender,
"StateSender.register: Not authorized to register"
);
registrations[receiver] = sender;
if (registrations[receiver] == address(0)) {
emit NewRegistration(msg.sender, sender, receiver);
} else {
emit RegistrationUpdated(msg.sender, sender, receiver);
}
}
}
contract Lockable is Governable {
bool public locked;
modifier onlyWhenUnlocked() {
require(!locked, "Is Locked");
_;
}
constructor(address _governance) public Governable(_governance) {}
function lock() external onlyGovernance {
locked = true;
}
function unlock() external onlyGovernance {
locked = false;
}
}
contract DepositManagerHeader {
event NewDepositBlock(address indexed owner, address indexed token, uint256 amountOrNFTId, uint256 depositBlockId);
event MaxErc20DepositUpdate(uint256 indexed oldLimit, uint256 indexed newLimit);
struct DepositBlock {
bytes32 depositHash;
uint256 createdAt;
}
}
contract DepositManagerStorage is ProxyStorage, Lockable, DepositManagerHeader {
Registry public registry;
RootChain public rootChain;
StateSender public stateSender;
mapping(uint256 => DepositBlock) public deposits;
address public childChain;
uint256 public maxErc20Deposit = 100 * (10**18);
}
contract DepositManager is DepositManagerStorage, IDepositManager, IERC721Receiver, ContractReceiver {
using SafeMath for uint256;
modifier isTokenMapped(address _token) {
require(registry.isTokenMapped(_token), "TOKEN_NOT_SUPPORTED");
_;
}
modifier isPredicateAuthorized() {
require(uint8(registry.predicates(msg.sender)) != 0, "Not a valid predicate");
_;
}
constructor() public Lockable(address(0x0)) {}
// deposit ETH by sending to this contract
function() external payable {
depositEther();
}
function updateMaxErc20Deposit(uint256 maxDepositAmount) public onlyGovernance {
require(maxDepositAmount != 0);
emit MaxErc20DepositUpdate(maxErc20Deposit, maxDepositAmount);
maxErc20Deposit = maxDepositAmount;
}
function transferAssets(
address _token,
address _user,
uint256 _amountOrNFTId
) external isPredicateAuthorized {
address wethToken = registry.getWethTokenAddress();
if (registry.isERC721(_token)) {
IERC721(_token).transferFrom(address(this), _user, _amountOrNFTId);
} else if (_token == wethToken) {
WETH t = WETH(_token);
t.withdraw(_amountOrNFTId, _user);
} else {
require(IERC20(_token).transfer(_user, _amountOrNFTId), "TRANSFER_FAILED");
}
}
function depositERC20(address _token, uint256 _amount) external {
depositERC20ForUser(_token, msg.sender, _amount);
}
function depositERC721(address _token, uint256 _tokenId) external {
depositERC721ForUser(_token, msg.sender, _tokenId);
}
function depositBulk(
address[] calldata _tokens,
uint256[] calldata _amountOrTokens,
address _user
)
external
onlyWhenUnlocked // unlike other deposit functions, depositBulk doesn't invoke _safeCreateDepositBlock
{
require(_tokens.length == _amountOrTokens.length, "Invalid Input");
uint256 depositId = rootChain.updateDepositId(_tokens.length);
Registry _registry = registry;
for (uint256 i = 0; i < _tokens.length; i++) {
// will revert if token is not mapped
if (_registry.isTokenMappedAndIsErc721(_tokens[i])) {
IERC721(_tokens[i]).transferFrom(msg.sender, address(this), _amountOrTokens[i]);
} else {
require(
IERC20(_tokens[i]).transferFrom(msg.sender, address(this), _amountOrTokens[i]),
"TOKEN_TRANSFER_FAILED"
);
}
_createDepositBlock(_user, _tokens[i], _amountOrTokens[i], depositId);
depositId = depositId.add(1);
}
}
/**
* @dev Caches childChain and stateSender (frequently used variables) from registry
*/
function updateChildChainAndStateSender() public {
(address _childChain, address _stateSender) = registry.getChildChainAndStateSender();
require(
_stateSender != address(stateSender) || _childChain != childChain,
"Atleast one of stateSender or childChain address should change"
);
childChain = _childChain;
stateSender = StateSender(_stateSender);
}
function depositERC20ForUser(
address _token,
address _user,
uint256 _amount
) public {
require(_amount <= maxErc20Deposit, "exceed maximum deposit amount");
require(IERC20(_token).transferFrom(msg.sender, address(this), _amount), "TOKEN_TRANSFER_FAILED");
_safeCreateDepositBlock(_user, _token, _amount);
}
function depositERC721ForUser(
address _token,
address _user,
uint256 _tokenId
) public {
IERC721(_token).transferFrom(msg.sender, address(this), _tokenId);
_safeCreateDepositBlock(_user, _token, _tokenId);
}
// @todo: write depositEtherForUser
function depositEther() public payable {
address wethToken = registry.getWethTokenAddress();
WETH t = WETH(wethToken);
t.deposit.value(msg.value)();
_safeCreateDepositBlock(msg.sender, wethToken, msg.value);
}
/**
* @notice This will be invoked when safeTransferFrom is called on the token contract to deposit tokens to this contract
without directly interacting with it
* @dev msg.sender is the token contract
* _operator The address which called `safeTransferFrom` function on the token contract
* @param _user The address which previously owned the token
* @param _tokenId The NFT identifier which is being transferred
* _data Additional data with no specified format
* @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
*/
function onERC721Received(
address, /* _operator */
address _user,
uint256 _tokenId,
bytes memory /* _data */
) public returns (bytes4) {
// the ERC721 contract address is the message sender
_safeCreateDepositBlock(
_user,
msg.sender,
/* token */
_tokenId
);
return 0x150b7a02;
}
// See https://github.com/ethereum/EIPs/issues/223
function tokenFallback(
address _user,
uint256 _amount,
bytes memory /* _data */
) public {
_safeCreateDepositBlock(
_user,
msg.sender,
/* token */
_amount
);
}
function _safeCreateDepositBlock(
address _user,
address _token,
uint256 _amountOrToken
) internal onlyWhenUnlocked isTokenMapped(_token) {
_createDepositBlock(
_user,
_token,
_amountOrToken,
rootChain.updateDepositId(1) /* returns _depositId */
);
}
function _createDepositBlock(
address _user,
address _token,
uint256 _amountOrToken,
uint256 _depositId
) internal {
deposits[_depositId] = DepositBlock(keccak256(abi.encodePacked(_user, _token, _amountOrToken)), now);
stateSender.syncState(childChain, abi.encode(_user, _token, _amountOrToken, _depositId));
emit NewDepositBlock(_user, _token, _amountOrToken, _depositId);
}
// Housekeeping function. @todo remove later
function updateRootChain(address _rootChain) public onlyOwner {
rootChain = RootChain(_rootChain);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"depositERC721ForUser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"updateChildChainAndStateSender","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"childChain","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amountOrNFTId","type":"uint256"}],"name":"transferAssets","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"maxDepositAmount","type":"uint256"}],"name":"updateMaxErc20Deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"governance","outputs":[{"internalType":"contract IGovernance","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"registry","outputs":[{"internalType":"contract Registry","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amountOrTokens","type":"uint256[]"},{"internalType":"address","name":"_user","type":"address"}],"name":"depositBulk","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositERC20ForUser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositERC20","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rootChain","outputs":[{"internalType":"contract RootChain","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"depositEther","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"unlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"deposits","outputs":[{"internalType":"bytes32","name":"depositHash","type":"bytes32"},{"internalType":"uint256","name":"createdAt","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"tokenFallback","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"stateSender","outputs":[{"internalType":"contract StateSender","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"locked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"depositERC721","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"maxErc20Deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rootChain","type":"address"}],"name":"updateRootChain","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"lock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOrNFTId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositBlockId","type":"uint256"}],"name":"NewDepositBlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldLimit","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"MaxErc20DepositUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]Contract Creation Code
608060405268056bc75e2d6310000060085534801561001d57600080fd5b50600080546001600160a01b031916331780825560405182916001600160a01b03169082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600280546001600160a01b0319166001600160a01b0392909216919091179055506119eb806100976000396000f3fe6080604052600436106101815760003560e01c806397feb926116100d1578063cb10f94c1161008a578063e7af7ba111610064578063e7af7ba1146106d2578063f2203711146106f9578063f2fde38b1461072c578063f83d08ba1461075f57610181565b8063cb10f94c1461066f578063cf30901214610684578063d29a4bf61461069957610181565b806397feb92614610503578063987ab9db1461053c57806398ea5fca14610181578063a69df4b514610551578063b02c43d014610566578063c0ee0b8a146105a957610181565b80635aa6e6751161013e5780637b1f7117116101185780637b1f7117146103ae5780638b9e4f93146104825780638da5cb5b146104c55780638f32d59b146104da57610181565b80635aa6e6751461036f578063715018a6146103845780637b1039991461039957610181565b8063072b15351461018b578063150b7a02146101ce57806342be8379146102bc57806342fc47fb146102d157806349f4cc17146103025780634b56c07114610345575b610189610774565b005b34801561019757600080fd5b50610189600480360360608110156101ae57600080fd5b506001600160a01b03813581169160208101359091169060400135610856565b3480156101da57600080fd5b5061029f600480360360808110156101f157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561022b57600080fd5b82018360208201111561023d57600080fd5b803590602001918460018302840111600160201b8311171561025e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506108d2945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156102c857600080fd5b506101896108f0565b3480156102dd57600080fd5b506102e6610a01565b604080516001600160a01b039092168252519081900360200190f35b34801561030e57600080fd5b506101896004803603606081101561032557600080fd5b506001600160a01b03813581169160208101359091169060400135610a10565b34801561035157600080fd5b506101896004803603602081101561036857600080fd5b5035610da1565b34801561037b57600080fd5b506102e6610e28565b34801561039057600080fd5b50610189610e37565b3480156103a557600080fd5b506102e6610e92565b3480156103ba57600080fd5b50610189600480360360608110156103d157600080fd5b810190602081018135600160201b8111156103eb57600080fd5b8201836020820111156103fd57600080fd5b803590602001918460208302840111600160201b8311171561041e57600080fd5b919390929091602081019035600160201b81111561043b57600080fd5b82018360208201111561044d57600080fd5b803590602001918460208302840111600160201b8311171561046e57600080fd5b9193509150356001600160a01b0316610ea1565b34801561048e57600080fd5b50610189600480360360608110156104a557600080fd5b506001600160a01b038135811691602081013590911690604001356112a4565b3480156104d157600080fd5b506102e66113d0565b3480156104e657600080fd5b506104ef6113df565b604080519115158252519081900360200190f35b34801561050f57600080fd5b506101896004803603604081101561052657600080fd5b506001600160a01b0381351690602001356113f0565b34801561054857600080fd5b506102e66113fb565b34801561055d57600080fd5b5061018961140a565b34801561057257600080fd5b506105906004803603602081101561058957600080fd5b5035611462565b6040805192835260208301919091528051918290030190f35b3480156105b557600080fd5b50610189600480360360608110156105cc57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156105fb57600080fd5b82018360208201111561060d57600080fd5b803590602001918460018302840111600160201b8311171561062e57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061147b945050505050565b34801561067b57600080fd5b506102e6611486565b34801561069057600080fd5b506104ef611495565b3480156106a557600080fd5b50610189600480360360408110156106bc57600080fd5b506001600160a01b0381351690602001356114a5565b3480156106de57600080fd5b506106e76114b0565b60408051918252519081900360200190f35b34801561070557600080fd5b506101896004803603602081101561071c57600080fd5b50356001600160a01b03166114b6565b34801561073857600080fd5b506101896004803603602081101561074f57600080fd5b50356001600160a01b03166114e9565b34801561076b57600080fd5b50610189611506565b60035460408051638b9c948960e01b815290516000926001600160a01b031691638b9c9489916004808301926020929190829003018186803b1580156107b957600080fd5b505afa1580156107cd573d6000803e3d6000fd5b505050506040513d60208110156107e357600080fd5b505160408051630d0e30db60e41b8152905191925082916001600160a01b0383169163d0e30db091349160048082019260009290919082900301818588803b15801561082e57600080fd5b505af1158015610842573d6000803e3d6000fd5b5050505050610852338334611564565b5050565b604080516323b872dd60e01b81523360048201523060248201526044810183905290516001600160a01b038516916323b872dd91606480830192600092919082900301818387803b1580156108aa57600080fd5b505af11580156108be573d6000803e3d6000fd5b505050506108cd828483611564565b505050565b60006108df843385611564565b50630a85bd0160e11b949350505050565b60035460408051630c91702f60e31b8152815160009384936001600160a01b039091169263648b81789260048083019392829003018186803b15801561093557600080fd5b505afa158015610949573d6000803e3d6000fd5b505050506040513d604081101561095f57600080fd5b50805160209091015160055491935091506001600160a01b03808316911614158061099857506007546001600160a01b03838116911614155b6109d35760405162461bcd60e51b815260040180806020018281038252603e815260200180611953603e913960400191505060405180910390fd5b600780546001600160a01b039384166001600160a01b03199182161790915560058054929093169116179055565b6007546001600160a01b031681565b600354604080516337b1d58560e01b815233600482015290516001600160a01b03909216916337b1d58591602480820192602092909190829003018186803b158015610a5b57600080fd5b505afa158015610a6f573d6000803e3d6000fd5b505050506040513d6020811015610a8557600080fd5b50516003811115610a9257fe5b60ff16610ade576040805162461bcd60e51b81526020600482015260156024820152744e6f7420612076616c69642070726564696361746560581b604482015290519081900360640190fd5b60035460408051638b9c948960e01b815290516000926001600160a01b031691638b9c9489916004808301926020929190829003018186803b158015610b2357600080fd5b505afa158015610b37573d6000803e3d6000fd5b505050506040513d6020811015610b4d57600080fd5b5051600354604080516336a8279560e21b81526001600160a01b038881166004830152915193945091169163daa09e5491602480820192602092909190829003018186803b158015610b9e57600080fd5b505afa158015610bb2573d6000803e3d6000fd5b505050506040513d6020811015610bc857600080fd5b505115610c4457604080516323b872dd60e01b81523060048201526001600160a01b038581166024830152604482018590529151918616916323b872dd9160648082019260009290919082900301818387803b158015610c2757600080fd5b505af1158015610c3b573d6000803e3d6000fd5b50505050610d9b565b806001600160a01b0316846001600160a01b03161415610ccc5760408051627b8a6760e11b8152600481018490526001600160a01b0385811660248301529151869283169162f714ce91604480830192600092919082900301818387803b158015610cae57600080fd5b505af1158015610cc2573d6000803e3d6000fd5b5050505050610d9b565b836001600160a01b031663a9059cbb84846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610d2c57600080fd5b505af1158015610d40573d6000803e3d6000fd5b505050506040513d6020811015610d5657600080fd5b5051610d9b576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b50505050565b6002546001600160a01b03163314610dea5760405162461bcd60e51b81526004018080602001828103825260268152602001806119916026913960400191505060405180910390fd5b80610df457600080fd5b6008546040518291907f010c0265813c273963aa5e8683cf5c45a3b744ba6369c22af0958ec5fcf16b2090600090a3600855565b6002546001600160a01b031681565b610e3f6113df565b610e4857600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6003546001600160a01b031681565b600254600160a01b900460ff1615610eec576040805162461bcd60e51b8152602060048201526009602482015268125cc8131bd8dad95960ba1b604482015290519081900360640190fd5b838214610f30576040805162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908125b9c1d5d609a1b604482015290519081900360640190fd5b6004805460408051635391f48360e01b8152928301879052516000926001600160a01b0390921691635391f48391602480830192602092919082900301818787803b158015610f7e57600080fd5b505af1158015610f92573d6000803e3d6000fd5b505050506040513d6020811015610fa857600080fd5b50516003549091506001600160a01b031660005b8681101561129a57816001600160a01b03166301f07db5898984818110610fdf57fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561103557600080fd5b505afa158015611049573d6000803e3d6000fd5b505050506040513d602081101561105f57600080fd5b50511561112a5787878281811061107257fe5b905060200201356001600160a01b03166001600160a01b03166323b872dd333089898681811061109e57fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561110d57600080fd5b505af1158015611121573d6000803e3d6000fd5b50505050611246565b87878281811061113657fe5b905060200201356001600160a01b03166001600160a01b03166323b872dd333089898681811061116257fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b1580156111d157600080fd5b505af11580156111e5573d6000803e3d6000fd5b505050506040513d60208110156111fb57600080fd5b5051611246576040805162461bcd60e51b81526020600482015260156024820152741513d2d15397d514905394d1915497d19052531151605a1b604482015290519081900360640190fd5b61127f8489898481811061125657fe5b905060200201356001600160a01b031688888581811061127257fe5b9050602002013586611701565b61129083600163ffffffff6118cb16565b9250600101610fbc565b5050505050505050565b6008548111156112fb576040805162461bcd60e51b815260206004820152601d60248201527f657863656564206d6178696d756d206465706f73697420616d6f756e74000000604482015290519081900360640190fd5b604080516323b872dd60e01b81523360048201523060248201526044810183905290516001600160a01b038516916323b872dd9160648083019260209291908290030181600087803b15801561135057600080fd5b505af1158015611364573d6000803e3d6000fd5b505050506040513d602081101561137a57600080fd5b50516113c5576040805162461bcd60e51b81526020600482015260156024820152741513d2d15397d514905394d1915497d19052531151605a1b604482015290519081900360640190fd5b6108cd828483611564565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b6108528233836112a4565b6004546001600160a01b031681565b6002546001600160a01b031633146114535760405162461bcd60e51b81526004018080602001828103825260268152602001806119916026913960400191505060405180910390fd5b6002805460ff60a01b19169055565b6006602052600090815260409020805460019091015482565b6108cd833384611564565b6005546001600160a01b031681565b600254600160a01b900460ff1681565b610852823383610856565b60085481565b6114be6113df565b6114c757600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6114f16113df565b6114fa57600080fd5b611503816118e4565b50565b6002546001600160a01b0316331461154f5760405162461bcd60e51b81526004018080602001828103825260268152602001806119916026913960400191505060405180910390fd5b6002805460ff60a01b1916600160a01b179055565b600254600160a01b900460ff16156115af576040805162461bcd60e51b8152602060048201526009602482015268125cc8131bd8dad95960ba1b604482015290519081900360640190fd5b60035460408051636416c18360e01b81526001600160a01b038086166004830152915185939290921691636416c18391602480820192602092909190829003018186803b1580156115ff57600080fd5b505afa158015611613573d6000803e3d6000fd5b505050506040513d602081101561162957600080fd5b5051611672576040805162461bcd60e51b81526020600482015260136024820152721513d2d15397d393d517d4d5541413d4951151606a1b604482015290519081900360640190fd5b610d9b848484600460009054906101000a90046001600160a01b03166001600160a01b0316635391f48360016040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156116d457600080fd5b505af11580156116e8573d6000803e3d6000fd5b505050506040513d60208110156116fe57600080fd5b50515b604080518082018252606086811b6bffffffffffffffffffffffff199081168284015286821b16607483015260888083018690528351808403909101815260a883018452805160209182012083524281840190815260008681526006835285812094518555905160019094019390935560055460075485516001600160a01b03808c1682860152808b168289015294810189905260808082018990528751808303909101815260a082018089526316f1983160e01b905291851660a4820181815260c48301988952835160e4840152835196909416976316f198319791969395909361010490930192908601918190849084905b8381101561180d5781810151838201526020016117f5565b50505050905090810190601f16801561183a5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561185a57600080fd5b505af115801561186e573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b03167f1dadc8d0683c6f9824e885935c1bec6f76816730dcec148dda8cf25a7b9f797b8484604051808381526020018281526020019250505060405180910390a350505050565b6000828201838110156118dd57600080fd5b9392505050565b6001600160a01b0381166118f757600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b039290921691909117905556fe41746c65617374206f6e65206f6620737461746553656e646572206f72206368696c64436861696e20616464726573732073686f756c64206368616e67654f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a72315820fa168237dcd05ed8461c994d8861a355492d574384104275b68d06cf6264c4ac64736f6c634300050b0032
Deployed Bytecode
0x6080604052600436106101815760003560e01c806397feb926116100d1578063cb10f94c1161008a578063e7af7ba111610064578063e7af7ba1146106d2578063f2203711146106f9578063f2fde38b1461072c578063f83d08ba1461075f57610181565b8063cb10f94c1461066f578063cf30901214610684578063d29a4bf61461069957610181565b806397feb92614610503578063987ab9db1461053c57806398ea5fca14610181578063a69df4b514610551578063b02c43d014610566578063c0ee0b8a146105a957610181565b80635aa6e6751161013e5780637b1f7117116101185780637b1f7117146103ae5780638b9e4f93146104825780638da5cb5b146104c55780638f32d59b146104da57610181565b80635aa6e6751461036f578063715018a6146103845780637b1039991461039957610181565b8063072b15351461018b578063150b7a02146101ce57806342be8379146102bc57806342fc47fb146102d157806349f4cc17146103025780634b56c07114610345575b610189610774565b005b34801561019757600080fd5b50610189600480360360608110156101ae57600080fd5b506001600160a01b03813581169160208101359091169060400135610856565b3480156101da57600080fd5b5061029f600480360360808110156101f157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b81111561022b57600080fd5b82018360208201111561023d57600080fd5b803590602001918460018302840111600160201b8311171561025e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506108d2945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156102c857600080fd5b506101896108f0565b3480156102dd57600080fd5b506102e6610a01565b604080516001600160a01b039092168252519081900360200190f35b34801561030e57600080fd5b506101896004803603606081101561032557600080fd5b506001600160a01b03813581169160208101359091169060400135610a10565b34801561035157600080fd5b506101896004803603602081101561036857600080fd5b5035610da1565b34801561037b57600080fd5b506102e6610e28565b34801561039057600080fd5b50610189610e37565b3480156103a557600080fd5b506102e6610e92565b3480156103ba57600080fd5b50610189600480360360608110156103d157600080fd5b810190602081018135600160201b8111156103eb57600080fd5b8201836020820111156103fd57600080fd5b803590602001918460208302840111600160201b8311171561041e57600080fd5b919390929091602081019035600160201b81111561043b57600080fd5b82018360208201111561044d57600080fd5b803590602001918460208302840111600160201b8311171561046e57600080fd5b9193509150356001600160a01b0316610ea1565b34801561048e57600080fd5b50610189600480360360608110156104a557600080fd5b506001600160a01b038135811691602081013590911690604001356112a4565b3480156104d157600080fd5b506102e66113d0565b3480156104e657600080fd5b506104ef6113df565b604080519115158252519081900360200190f35b34801561050f57600080fd5b506101896004803603604081101561052657600080fd5b506001600160a01b0381351690602001356113f0565b34801561054857600080fd5b506102e66113fb565b34801561055d57600080fd5b5061018961140a565b34801561057257600080fd5b506105906004803603602081101561058957600080fd5b5035611462565b6040805192835260208301919091528051918290030190f35b3480156105b557600080fd5b50610189600480360360608110156105cc57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156105fb57600080fd5b82018360208201111561060d57600080fd5b803590602001918460018302840111600160201b8311171561062e57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061147b945050505050565b34801561067b57600080fd5b506102e6611486565b34801561069057600080fd5b506104ef611495565b3480156106a557600080fd5b50610189600480360360408110156106bc57600080fd5b506001600160a01b0381351690602001356114a5565b3480156106de57600080fd5b506106e76114b0565b60408051918252519081900360200190f35b34801561070557600080fd5b506101896004803603602081101561071c57600080fd5b50356001600160a01b03166114b6565b34801561073857600080fd5b506101896004803603602081101561074f57600080fd5b50356001600160a01b03166114e9565b34801561076b57600080fd5b50610189611506565b60035460408051638b9c948960e01b815290516000926001600160a01b031691638b9c9489916004808301926020929190829003018186803b1580156107b957600080fd5b505afa1580156107cd573d6000803e3d6000fd5b505050506040513d60208110156107e357600080fd5b505160408051630d0e30db60e41b8152905191925082916001600160a01b0383169163d0e30db091349160048082019260009290919082900301818588803b15801561082e57600080fd5b505af1158015610842573d6000803e3d6000fd5b5050505050610852338334611564565b5050565b604080516323b872dd60e01b81523360048201523060248201526044810183905290516001600160a01b038516916323b872dd91606480830192600092919082900301818387803b1580156108aa57600080fd5b505af11580156108be573d6000803e3d6000fd5b505050506108cd828483611564565b505050565b60006108df843385611564565b50630a85bd0160e11b949350505050565b60035460408051630c91702f60e31b8152815160009384936001600160a01b039091169263648b81789260048083019392829003018186803b15801561093557600080fd5b505afa158015610949573d6000803e3d6000fd5b505050506040513d604081101561095f57600080fd5b50805160209091015160055491935091506001600160a01b03808316911614158061099857506007546001600160a01b03838116911614155b6109d35760405162461bcd60e51b815260040180806020018281038252603e815260200180611953603e913960400191505060405180910390fd5b600780546001600160a01b039384166001600160a01b03199182161790915560058054929093169116179055565b6007546001600160a01b031681565b600354604080516337b1d58560e01b815233600482015290516001600160a01b03909216916337b1d58591602480820192602092909190829003018186803b158015610a5b57600080fd5b505afa158015610a6f573d6000803e3d6000fd5b505050506040513d6020811015610a8557600080fd5b50516003811115610a9257fe5b60ff16610ade576040805162461bcd60e51b81526020600482015260156024820152744e6f7420612076616c69642070726564696361746560581b604482015290519081900360640190fd5b60035460408051638b9c948960e01b815290516000926001600160a01b031691638b9c9489916004808301926020929190829003018186803b158015610b2357600080fd5b505afa158015610b37573d6000803e3d6000fd5b505050506040513d6020811015610b4d57600080fd5b5051600354604080516336a8279560e21b81526001600160a01b038881166004830152915193945091169163daa09e5491602480820192602092909190829003018186803b158015610b9e57600080fd5b505afa158015610bb2573d6000803e3d6000fd5b505050506040513d6020811015610bc857600080fd5b505115610c4457604080516323b872dd60e01b81523060048201526001600160a01b038581166024830152604482018590529151918616916323b872dd9160648082019260009290919082900301818387803b158015610c2757600080fd5b505af1158015610c3b573d6000803e3d6000fd5b50505050610d9b565b806001600160a01b0316846001600160a01b03161415610ccc5760408051627b8a6760e11b8152600481018490526001600160a01b0385811660248301529151869283169162f714ce91604480830192600092919082900301818387803b158015610cae57600080fd5b505af1158015610cc2573d6000803e3d6000fd5b5050505050610d9b565b836001600160a01b031663a9059cbb84846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610d2c57600080fd5b505af1158015610d40573d6000803e3d6000fd5b505050506040513d6020811015610d5657600080fd5b5051610d9b576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b50505050565b6002546001600160a01b03163314610dea5760405162461bcd60e51b81526004018080602001828103825260268152602001806119916026913960400191505060405180910390fd5b80610df457600080fd5b6008546040518291907f010c0265813c273963aa5e8683cf5c45a3b744ba6369c22af0958ec5fcf16b2090600090a3600855565b6002546001600160a01b031681565b610e3f6113df565b610e4857600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6003546001600160a01b031681565b600254600160a01b900460ff1615610eec576040805162461bcd60e51b8152602060048201526009602482015268125cc8131bd8dad95960ba1b604482015290519081900360640190fd5b838214610f30576040805162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908125b9c1d5d609a1b604482015290519081900360640190fd5b6004805460408051635391f48360e01b8152928301879052516000926001600160a01b0390921691635391f48391602480830192602092919082900301818787803b158015610f7e57600080fd5b505af1158015610f92573d6000803e3d6000fd5b505050506040513d6020811015610fa857600080fd5b50516003549091506001600160a01b031660005b8681101561129a57816001600160a01b03166301f07db5898984818110610fdf57fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561103557600080fd5b505afa158015611049573d6000803e3d6000fd5b505050506040513d602081101561105f57600080fd5b50511561112a5787878281811061107257fe5b905060200201356001600160a01b03166001600160a01b03166323b872dd333089898681811061109e57fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561110d57600080fd5b505af1158015611121573d6000803e3d6000fd5b50505050611246565b87878281811061113657fe5b905060200201356001600160a01b03166001600160a01b03166323b872dd333089898681811061116257fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b1580156111d157600080fd5b505af11580156111e5573d6000803e3d6000fd5b505050506040513d60208110156111fb57600080fd5b5051611246576040805162461bcd60e51b81526020600482015260156024820152741513d2d15397d514905394d1915497d19052531151605a1b604482015290519081900360640190fd5b61127f8489898481811061125657fe5b905060200201356001600160a01b031688888581811061127257fe5b9050602002013586611701565b61129083600163ffffffff6118cb16565b9250600101610fbc565b5050505050505050565b6008548111156112fb576040805162461bcd60e51b815260206004820152601d60248201527f657863656564206d6178696d756d206465706f73697420616d6f756e74000000604482015290519081900360640190fd5b604080516323b872dd60e01b81523360048201523060248201526044810183905290516001600160a01b038516916323b872dd9160648083019260209291908290030181600087803b15801561135057600080fd5b505af1158015611364573d6000803e3d6000fd5b505050506040513d602081101561137a57600080fd5b50516113c5576040805162461bcd60e51b81526020600482015260156024820152741513d2d15397d514905394d1915497d19052531151605a1b604482015290519081900360640190fd5b6108cd828483611564565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b6108528233836112a4565b6004546001600160a01b031681565b6002546001600160a01b031633146114535760405162461bcd60e51b81526004018080602001828103825260268152602001806119916026913960400191505060405180910390fd5b6002805460ff60a01b19169055565b6006602052600090815260409020805460019091015482565b6108cd833384611564565b6005546001600160a01b031681565b600254600160a01b900460ff1681565b610852823383610856565b60085481565b6114be6113df565b6114c757600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6114f16113df565b6114fa57600080fd5b611503816118e4565b50565b6002546001600160a01b0316331461154f5760405162461bcd60e51b81526004018080602001828103825260268152602001806119916026913960400191505060405180910390fd5b6002805460ff60a01b1916600160a01b179055565b600254600160a01b900460ff16156115af576040805162461bcd60e51b8152602060048201526009602482015268125cc8131bd8dad95960ba1b604482015290519081900360640190fd5b60035460408051636416c18360e01b81526001600160a01b038086166004830152915185939290921691636416c18391602480820192602092909190829003018186803b1580156115ff57600080fd5b505afa158015611613573d6000803e3d6000fd5b505050506040513d602081101561162957600080fd5b5051611672576040805162461bcd60e51b81526020600482015260136024820152721513d2d15397d393d517d4d5541413d4951151606a1b604482015290519081900360640190fd5b610d9b848484600460009054906101000a90046001600160a01b03166001600160a01b0316635391f48360016040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156116d457600080fd5b505af11580156116e8573d6000803e3d6000fd5b505050506040513d60208110156116fe57600080fd5b50515b604080518082018252606086811b6bffffffffffffffffffffffff199081168284015286821b16607483015260888083018690528351808403909101815260a883018452805160209182012083524281840190815260008681526006835285812094518555905160019094019390935560055460075485516001600160a01b03808c1682860152808b168289015294810189905260808082018990528751808303909101815260a082018089526316f1983160e01b905291851660a4820181815260c48301988952835160e4840152835196909416976316f198319791969395909361010490930192908601918190849084905b8381101561180d5781810151838201526020016117f5565b50505050905090810190601f16801561183a5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561185a57600080fd5b505af115801561186e573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b03167f1dadc8d0683c6f9824e885935c1bec6f76816730dcec148dda8cf25a7b9f797b8484604051808381526020018281526020019250505060405180910390a350505050565b6000828201838110156118dd57600080fd5b9392505050565b6001600160a01b0381166118f757600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b039290921691909117905556fe41746c65617374206f6e65206f6620737461746553656e646572206f72206368696c64436861696e20616464726573732073686f756c64206368616e67654f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a72315820fa168237dcd05ed8461c994d8861a355492d574384104275b68d06cf6264c4ac64736f6c634300050b0032
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.