Overview
ETH Balance
0.00001 ETH
Eth Value
$0.03 (@ $3,420.63/ETH)More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,881 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Process Exits | 21277802 | 50 mins ago | IN | 0 ETH | 0.00243815 | ||||
Process Exits | 21272784 | 17 hrs ago | IN | 0 ETH | 0.00281703 | ||||
Process Exits | 21272493 | 18 hrs ago | IN | 0 ETH | 0.00236804 | ||||
Process Exits | 21269711 | 27 hrs ago | IN | 0 ETH | 0.00084621 | ||||
Process Exits | 21266206 | 39 hrs ago | IN | 0 ETH | 0.00297941 | ||||
Process Exits | 21263147 | 2 days ago | IN | 0 ETH | 0.00100574 | ||||
Process Exits | 21261110 | 2 days ago | IN | 0 ETH | 0.00155067 | ||||
Process Exits | 21256841 | 2 days ago | IN | 0 ETH | 0.00024617 | ||||
Process Exits | 21256828 | 2 days ago | IN | 0 ETH | 0.0011409 | ||||
Process Exits | 21254047 | 3 days ago | IN | 0 ETH | 0.00186381 | ||||
Process Exits | 21252154 | 3 days ago | IN | 0 ETH | 0.00278028 | ||||
Process Exits | 21250689 | 3 days ago | IN | 0 ETH | 0.00190486 | ||||
Process Exits | 21246131 | 4 days ago | IN | 0 ETH | 0.0025035 | ||||
Process Exits | 21245399 | 4 days ago | IN | 0 ETH | 0.00260375 | ||||
Process Exits | 21244459 | 4 days ago | IN | 0 ETH | 0.00261872 | ||||
Process Exits | 21243188 | 4 days ago | IN | 0 ETH | 0.00128396 | ||||
Process Exits | 21243046 | 4 days ago | IN | 0 ETH | 0.00224438 | ||||
Process Exits | 21241479 | 5 days ago | IN | 0 ETH | 0.00178816 | ||||
Process Exits | 21231980 | 6 days ago | IN | 0 ETH | 0.00184353 | ||||
Process Exits | 21228366 | 6 days ago | IN | 0 ETH | 0.00211889 | ||||
Process Exits | 21226782 | 7 days ago | IN | 0 ETH | 0.00035373 | ||||
Process Exits | 21226777 | 7 days ago | IN | 0 ETH | 0.00279126 | ||||
Process Exits | 21225167 | 7 days ago | IN | 0 ETH | 0.00164361 | ||||
Process Exits | 21220553 | 8 days ago | IN | 0 ETH | 0.00035398 | ||||
Process Exits | 21220544 | 8 days ago | IN | 0 ETH | 0.00170977 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
17868231 | 477 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
WithdrawManagerProxy
Compiler Version
v0.5.17+commit.d19bba13
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-08-07 */ pragma solidity ^0.5.2; interface IGovernance { function update(address target, bytes calldata data) external; } contract Governable { IGovernance public governance; constructor(address _governance) public { governance = IGovernance(_governance); } modifier onlyGovernance() { _assertGovernance(); _; } function _assertGovernance() private view { 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]; } } /* * SPDX-License-Identitifer: MIT */ // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-897.md interface ERCProxy { function proxyType() external pure returns (uint256 proxyTypeId); function implementation() external view returns (address codeAddr); } contract DelegateProxyForwarder { function delegatedFwd(address _dst, bytes memory _calldata) internal { // solium-disable-next-line security/no-inline-assembly assembly { let result := delegatecall( sub(gas, 10000), _dst, add(_calldata, 0x20), mload(_calldata), 0, 0 ) let size := returndatasize let ptr := mload(0x40) returndatacopy(ptr, 0, size) // revert instead of invalid() bc if the underlying call failed with invalid() it already wasted gas. // if the call returned error data, forward it switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } function isContract(address _target) internal view returns (bool) { if (_target == address(0)) { return false; } uint256 size; assembly { size := extcodesize(_target) } return size > 0; } } contract DelegateProxy is ERCProxy, DelegateProxyForwarder { function proxyType() external pure returns (uint256 proxyTypeId) { // Upgradeable proxy proxyTypeId = 2; } function implementation() external view returns (address); } /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ 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 Proxy is ProxyStorage, DelegateProxy { event ProxyUpdated(address indexed _new, address indexed _old); event OwnerUpdate(address _prevOwner, address _newOwner); constructor(address _proxyTo) public { updateImplementation(_proxyTo); } function() external payable { // require(currentContract != 0, "If app code has not been set yet, do not call"); // Todo: filter out some calls or handle in the end fallback delegatedFwd(proxyTo, msg.data); } function implementation() external view returns (address) { return proxyTo; } function updateImplementation(address _newProxyTo) public onlyOwner { require(_newProxyTo != address(0x0), "INVALID_PROXY_ADDRESS"); require(isContract(_newProxyTo), "DESTINATION_ADDRESS_IS_NOT_A_CONTRACT"); emit ProxyUpdated(_newProxyTo, proxyTo); proxyTo = _newProxyTo; } function isContract(address _target) internal view returns (bool) { if (_target == address(0)) { return false; } uint256 size; assembly { size := extcodesize(_target) } return size > 0; } } /* * @author Hamdi Allam [email protected] * Please reach out with any questions or concerns */ 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)) } } } /** * @title SafeMath * @dev Unsigned math operations with safety checks that revert on error */ 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 ChainIdMixin { bytes constant public networkId = hex"6D"; uint256 constant public CHAINID = 109; } 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, bool acceptDelegation, bytes calldata signerPubkey ) external; function confirmAuctionBid(uint256 validatorId, uint256 heimdallFee) external; function transferFunds( uint256 validatorId, uint256 amount, address delegator ) external returns (bool); function delegationDeposit( uint256 validatorId, uint256 amount, address delegator ) external returns (bool); function unstake(uint256 validatorId) external; function totalStakedFor(address addr) external view returns (uint256); function stakeFor( address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey ) public; function checkSignatures( uint256 blockInterval, bytes32 voteHash, bytes32 stateRoot, address proposer, uint[3][] calldata sigs ) external returns (uint256); function updateValidatorState(uint256 validatorId, int256 amount) public; function ownerOf(uint256 tokenId) public view returns (address); function slash(bytes calldata slashingInfoList) external returns (uint256); function validatorStake(uint256 validatorId) public view returns (uint256); function epoch() public view returns (uint256); function getRegistry() public view returns (address); function withdrawalDelay() public view returns (uint256); function delegatedAmount(uint256 validatorId) public view returns(uint256); function decreaseValidatorDelegatedAmount(uint256 validatorId, uint256 amount) public; function withdrawDelegatorsReward(uint256 validatorId) public returns(uint256); function delegatorsReward(uint256 validatorId) public view returns(uint256); function dethroneAndStake( address auctionUser, uint256 heimdallFee, uint256 validatorId, uint256 auctionAmount, bool acceptDelegation, bytes calldata signerPubkey ) external; } interface IRootChain { function slash() external; function submitHeaderBlock(bytes calldata data, bytes calldata sigs) external; function submitCheckpoint(bytes calldata data, uint[3][] 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 { revert(); } function submitCheckpoint(bytes calldata data, uint[3][] 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)); } } /** * @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); } /** * @title ERC721 Non-Fungible Token Standard basic interface * @dev see https://eips.ethereum.org/EIPS/eip-721 */ 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; } /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ 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); } /** * Utility library of inline functions on addresses */ library Address { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param account address of the account to check * @return whether the target address is a contract */ function isContract(address account) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids * * Include with `using Counters for Counters.Counter;` * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never * directly accessed. */ library Counters { using SafeMath for uint256; struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { counter._value += 1; } function decrement(Counter storage counter) internal { counter._value = counter._value.sub(1); } } /** * @title ERC165 * @author Matt Condon (@shrugs) * @dev Implements ERC165 using a lookup table. */ contract ERC165 is IERC165 { bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /* * 0x01ffc9a7 === * bytes4(keccak256('supportsInterface(bytes4)')) */ /** * @dev a mapping of interface id to whether or not it's supported */ mapping(bytes4 => bool) private _supportedInterfaces; /** * @dev A contract implementing SupportsInterfaceWithLookup * implement ERC165 itself */ constructor () internal { _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev implement supportsInterface(bytes4) using a lookup table */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev internal method for registering an interface */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff); _supportedInterfaces[interfaceId] = true; } } /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://eips.ethereum.org/EIPS/eip-721 */ contract ERC721 is ERC165, IERC721 { using SafeMath for uint256; using Address for address; using Counters for Counters.Counter; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from token ID to owner mapping (uint256 => address) private _tokenOwner; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to number of owned token mapping (address => Counters.Counter) private _ownedTokensCount; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; /* * 0x80ac58cd === * bytes4(keccak256('balanceOf(address)')) ^ * bytes4(keccak256('ownerOf(uint256)')) ^ * bytes4(keccak256('approve(address,uint256)')) ^ * bytes4(keccak256('getApproved(uint256)')) ^ * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ * bytes4(keccak256('isApprovedForAll(address,address)')) ^ * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) */ constructor () public { // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721); } /** * @dev Gets the balance of the specified address * @param owner address to query the balance of * @return uint256 representing the amount owned by the passed address */ function balanceOf(address owner) public view returns (uint256) { require(owner != address(0)); return _ownedTokensCount[owner].current(); } /** * @dev Gets the owner of the specified token ID * @param tokenId uint256 ID of the token to query the owner of * @return address currently marked as the owner of the given token ID */ function ownerOf(uint256 tokenId) public view returns (address) { address owner = _tokenOwner[tokenId]; require(owner != address(0)); return owner; } /** * @dev Approves another address to transfer the given token ID * The zero address indicates there is no approved address. * There can only be one approved address per token at a given time. * Can only be called by the token owner or an approved operator. * @param to address to be approved for the given token ID * @param tokenId uint256 ID of the token to be approved */ function approve(address to, uint256 tokenId) public { address owner = ownerOf(tokenId); require(to != owner); require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev Gets the approved address for a token ID, or zero if no address set * Reverts if the token ID does not exist. * @param tokenId uint256 ID of the token to query the approval of * @return address currently approved for the given token ID */ function getApproved(uint256 tokenId) public view returns (address) { require(_exists(tokenId)); return _tokenApprovals[tokenId]; } /** * @dev Sets or unsets the approval of a given operator * An operator is allowed to transfer all tokens of the sender on their behalf * @param to operator address to set the approval * @param approved representing the status of the approval to be set */ function setApprovalForAll(address to, bool approved) public { require(to != msg.sender); _operatorApprovals[msg.sender][to] = approved; emit ApprovalForAll(msg.sender, to, approved); } /** * @dev Tells whether an operator is approved by a given owner * @param owner owner address which you want to query the approval of * @param operator operator address which you want to query the approval of * @return bool whether the given operator is approved by the given owner */ function isApprovedForAll(address owner, address operator) public view returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Transfers the ownership of a given token ID to another address * Usage of this method is discouraged, use `safeTransferFrom` whenever possible * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function transferFrom(address from, address to, uint256 tokenId) public { require(_isApprovedOrOwner(msg.sender, tokenId)); _transferFrom(from, to, tokenId); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function safeTransferFrom(address from, address to, uint256 tokenId) public { safeTransferFrom(from, to, tokenId, ""); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { transferFrom(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data)); } /** * @dev Returns whether the specified token exists * @param tokenId uint256 ID of the token to query the existence of * @return bool whether the token exists */ function _exists(uint256 tokenId) internal view returns (bool) { address owner = _tokenOwner[tokenId]; return owner != address(0); } /** * @dev Returns whether the given spender can transfer a given token ID * @param spender address of the spender to query * @param tokenId uint256 ID of the token to be transferred * @return bool whether the msg.sender is approved for the given token ID, * is an operator of the owner, or is the owner of the token */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { address owner = ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Internal function to mint a new token * Reverts if the given token ID already exists * @param to The address that will own the minted token * @param tokenId uint256 ID of the token to be minted */ function _mint(address to, uint256 tokenId) internal { require(to != address(0)); require(!_exists(tokenId)); _tokenOwner[tokenId] = to; _ownedTokensCount[to].increment(); emit Transfer(address(0), to, tokenId); } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * Deprecated, use _burn(uint256) instead. * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { require(ownerOf(tokenId) == owner); _clearApproval(tokenId); _ownedTokensCount[owner].decrement(); _tokenOwner[tokenId] = address(0); emit Transfer(owner, address(0), tokenId); } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * @param tokenId uint256 ID of the token being burned */ function _burn(uint256 tokenId) internal { _burn(ownerOf(tokenId), tokenId); } /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to transferFrom, this imposes no restrictions on msg.sender. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function _transferFrom(address from, address to, uint256 tokenId) internal { require(ownerOf(tokenId) == from); require(to != address(0)); _clearApproval(tokenId); _ownedTokensCount[from].decrement(); _ownedTokensCount[to].increment(); _tokenOwner[tokenId] = to; emit Transfer(from, to, tokenId); } /** * @dev Internal function to invoke `onERC721Received` on a target address * The call is not executed if the target address is not a contract * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) internal returns (bool) { if (!to.isContract()) { return true; } bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data); return (retval == _ERC721_RECEIVED); } /** * @dev Private function to clear current approval of a given token ID * @param tokenId uint256 ID of the token to be transferred */ function _clearApproval(uint256 tokenId) private { if (_tokenApprovals[tokenId] != address(0)) { _tokenApprovals[tokenId] = address(0); } } } contract ExitNFT is ERC721 { Registry internal registry; modifier onlyWithdrawManager() { require( msg.sender == registry.getWithdrawManagerAddress(), "UNAUTHORIZED_WITHDRAW_MANAGER_ONLY" ); _; } constructor(address _registry) public { registry = Registry(_registry); } function mint(address _owner, uint256 _tokenId) external onlyWithdrawManager { _mint(_owner, _tokenId); } function burn(uint256 _tokenId) external onlyWithdrawManager { _burn(_tokenId); } function exists(uint256 tokenId) public view returns (bool) { return _exists(tokenId); } } contract ExitsDataStructure { struct Input { address utxoOwner; address predicate; address token; } struct PlasmaExit { uint256 receiptAmountOrNFTId; bytes32 txHash; address owner; address token; bool isRegularExit; address predicate; // Mapping from age of input to Input mapping(uint256 => Input) inputs; } } contract WithdrawManagerHeader is ExitsDataStructure { event Withdraw(uint256 indexed exitId, address indexed user, address indexed token, uint256 amount); event ExitStarted( address indexed exitor, uint256 indexed exitId, address indexed token, uint256 amount, bool isRegularExit ); event ExitUpdated(uint256 indexed exitId, uint256 indexed age, address signer); event ExitPeriodUpdate(uint256 indexed oldExitPeriod, uint256 indexed newExitPeriod); event ExitCancelled(uint256 indexed exitId); } contract WithdrawManagerStorage is ProxyStorage, WithdrawManagerHeader { // 0.5 week = 7 * 86400 / 2 = 302400 uint256 public HALF_EXIT_PERIOD = 302400; // Bonded exits collaterized at 0.1 ETH uint256 internal constant BOND_AMOUNT = 10**17; Registry internal registry; RootChain internal rootChain; mapping(uint128 => bool) isKnownExit; mapping(uint256 => PlasmaExit) public exits; // mapping with token => (owner => exitId) keccak(token+owner) keccak(token+owner+tokenId) mapping(bytes32 => uint256) public ownerExits; mapping(address => address) public exitsQueues; ExitNFT public exitNft; // ERC721, ERC20 and Weth transfers require 155000, 100000, 52000 gas respectively // Processing each exit in a while loop iteration requires ~52000 gas (@todo check if this changed) // uint32 constant internal ITERATION_GAS = 52000; // So putting an upper limit of 155000 + 52000 + leeway uint32 public ON_FINALIZE_GAS_LIMIT = 300000; uint256 public exitWindow; } contract WithdrawManagerProxy is Proxy, WithdrawManagerStorage { constructor( address _proxyTo, address _registry, address _rootChain, address _exitNft ) public Proxy(_proxyTo) { registry = Registry(_registry); rootChain = RootChain(_rootChain); exitNft = ExitNFT(_exitNft); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_proxyTo","type":"address"},{"internalType":"address","name":"_registry","type":"address"},{"internalType":"address","name":"_rootChain","type":"address"},{"internalType":"address","name":"_exitNft","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"exitId","type":"uint256"}],"name":"ExitCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldExitPeriod","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newExitPeriod","type":"uint256"}],"name":"ExitPeriodUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exitor","type":"address"},{"indexed":true,"internalType":"uint256","name":"exitId","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isRegularExit","type":"bool"}],"name":"ExitStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"exitId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"age","type":"uint256"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"ExitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_prevOwner","type":"address"},{"indexed":false,"internalType":"address","name":"_newOwner","type":"address"}],"name":"OwnerUpdate","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_new","type":"address"},{"indexed":true,"internalType":"address","name":"_old","type":"address"}],"name":"ProxyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"exitId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"HALF_EXIT_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ON_FINALIZE_GAS_LIMIT","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"exitNft","outputs":[{"internalType":"contract ExitNFT","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"exitWindow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"exits","outputs":[{"internalType":"uint256","name":"receiptAmountOrNFTId","type":"uint256"},{"internalType":"bytes32","name":"txHash","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"isRegularExit","type":"bool"},{"internalType":"address","name":"predicate","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"exitsQueues","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"implementation","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":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"ownerExits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"proxyType","outputs":[{"internalType":"uint256","name":"proxyTypeId","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","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":[{"internalType":"address","name":"_newProxyTo","type":"address"}],"name":"updateImplementation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405262049d406002556009805463ffffffff60a01b191661249f60a51b17905534801561002e57600080fd5b506040516109663803806109668339818101604052608081101561005157600080fd5b5080516020820151604080840151606090940151600080546001600160a01b0319163317808255925194959394919286926001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36100c7816001600160e01b0361010b16565b50600380546001600160a01b039485166001600160a01b0319918216179091556004805493851693821693909317909255600980549190931691161790555061025e565b61011c6001600160e01b0361022a16565b61012557600080fd5b6001600160a01b038116610180576040805162461bcd60e51b815260206004820152601560248201527f494e56414c49445f50524f58595f414444524553530000000000000000000000604482015290519081900360640190fd5b610192816001600160e01b0361023b16565b6101cd5760405162461bcd60e51b81526004018080602001828103825260258152602001806109416025913960400191505060405180910390fd5b6001546040516001600160a01b03918216918316907fd32d24edea94f55e932d9a008afc425a8561462d1b1f57bc6e508e9a6b9509e190600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331490565b60006001600160a01b03821661025357506000610259565b50803b15155b919050565b6106d48061026d6000396000f3fe6080604052600436106100dd5760003560e01c80638da5cb5b1161007f578063d11f045c11610059578063d11f045c146102dc578063ed4a0be81461030f578063edeca09b14610324578063f2fde38b14610339576100dd565b80638da5cb5b146102705780638f32d59b1461028557806396cbd812146102ae576100dd565b80634555d5c9116100bb5780634555d5c9146101eb5780635c60da1b14610200578063661429c814610231578063715018a61461025b576100dd565b8063025b22bc146101295780631e29848b1461015c578063342de17914610183575b60015460408051602036601f8101829004820283018201909352828252610127936001600160a01b0316926000918190840183828082843760009201919091525061036c92505050565b005b34801561013557600080fd5b506101276004803603602081101561014c57600080fd5b50356001600160a01b0316610394565b34801561016857600080fd5b50610171610499565b60408051918252519081900360200190f35b34801561018f57600080fd5b506101ad600480360360208110156101a657600080fd5b503561049f565b6040805196875260208701959095526001600160a01b03938416868601529183166060860152151560808501521660a0830152519081900360c00190f35b3480156101f757600080fd5b506101716104e8565b34801561020c57600080fd5b506102156104ed565b604080516001600160a01b039092168252519081900360200190f35b34801561023d57600080fd5b506101716004803603602081101561025457600080fd5b50356104fc565b34801561026757600080fd5b5061012761050e565b34801561027c57600080fd5b50610215610569565b34801561029157600080fd5b5061029a610578565b604080519115158252519081900360200190f35b3480156102ba57600080fd5b506102c3610589565b6040805163ffffffff9092168252519081900360200190f35b3480156102e857600080fd5b50610215600480360360208110156102ff57600080fd5b50356001600160a01b031661059c565b34801561031b57600080fd5b506101716105b7565b34801561033057600080fd5b506102156105bd565b34801561034557600080fd5b506101276004803603602081101561035c57600080fd5b50356001600160a01b03166105cc565b600080825160208401856127105a03f43d604051816000823e828015610390578282f35b8282fd5b61039c610578565b6103a557600080fd5b6001600160a01b0381166103f8576040805162461bcd60e51b8152602060048201526015602482015274494e56414c49445f50524f58595f4144445245535360581b604482015290519081900360640190fd5b610401816105e9565b61043c5760405162461bcd60e51b815260040180806020018281038252602581526020018061067b6025913960400191505060405180910390fd5b6001546040516001600160a01b03918216918316907fd32d24edea94f55e932d9a008afc425a8561462d1b1f57bc6e508e9a6b9509e190600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600a5481565b60066020526000908152604090208054600182015460028301546003840154600490940154929391926001600160a01b039182169282811692600160a01b90910460ff16911686565b600290565b6001546001600160a01b031690565b60076020526000908152604090205481565b610516610578565b61051f57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b600954600160a01b900463ffffffff1681565b6008602052600090815260409020546001600160a01b031681565b60025481565b6009546001600160a01b031681565b6105d4610578565b6105dd57600080fd5b6105e68161060c565b50565b60006001600160a01b03821661060157506000610607565b50803b15155b919050565b6001600160a01b03811661061f57600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b039290921691909117905556fe44455354494e4154494f4e5f414444524553535f49535f4e4f545f415f434f4e5452414354a265627a7a723158204f0a156c7a5b0c8f2b19d47213adb8e80be82464da678d00feb66a88eb880bd964736f6c6343000511003244455354494e4154494f4e5f414444524553535f49535f4e4f545f415f434f4e5452414354000000000000000000000000ceca73676b6bfed2d7673d131201f733f84b51df000000000000000000000000f486e3b6a432bdd6edaae85a565cd7682a7862bb000000000000000000000000d46042f503b8ec0a166af8c0bfbb0a3c562353f90000000000000000000000007ad7f98f229c5c1ea5161bed952c3007dbe1f307
Deployed Bytecode
0x6080604052600436106100dd5760003560e01c80638da5cb5b1161007f578063d11f045c11610059578063d11f045c146102dc578063ed4a0be81461030f578063edeca09b14610324578063f2fde38b14610339576100dd565b80638da5cb5b146102705780638f32d59b1461028557806396cbd812146102ae576100dd565b80634555d5c9116100bb5780634555d5c9146101eb5780635c60da1b14610200578063661429c814610231578063715018a61461025b576100dd565b8063025b22bc146101295780631e29848b1461015c578063342de17914610183575b60015460408051602036601f8101829004820283018201909352828252610127936001600160a01b0316926000918190840183828082843760009201919091525061036c92505050565b005b34801561013557600080fd5b506101276004803603602081101561014c57600080fd5b50356001600160a01b0316610394565b34801561016857600080fd5b50610171610499565b60408051918252519081900360200190f35b34801561018f57600080fd5b506101ad600480360360208110156101a657600080fd5b503561049f565b6040805196875260208701959095526001600160a01b03938416868601529183166060860152151560808501521660a0830152519081900360c00190f35b3480156101f757600080fd5b506101716104e8565b34801561020c57600080fd5b506102156104ed565b604080516001600160a01b039092168252519081900360200190f35b34801561023d57600080fd5b506101716004803603602081101561025457600080fd5b50356104fc565b34801561026757600080fd5b5061012761050e565b34801561027c57600080fd5b50610215610569565b34801561029157600080fd5b5061029a610578565b604080519115158252519081900360200190f35b3480156102ba57600080fd5b506102c3610589565b6040805163ffffffff9092168252519081900360200190f35b3480156102e857600080fd5b50610215600480360360208110156102ff57600080fd5b50356001600160a01b031661059c565b34801561031b57600080fd5b506101716105b7565b34801561033057600080fd5b506102156105bd565b34801561034557600080fd5b506101276004803603602081101561035c57600080fd5b50356001600160a01b03166105cc565b600080825160208401856127105a03f43d604051816000823e828015610390578282f35b8282fd5b61039c610578565b6103a557600080fd5b6001600160a01b0381166103f8576040805162461bcd60e51b8152602060048201526015602482015274494e56414c49445f50524f58595f4144445245535360581b604482015290519081900360640190fd5b610401816105e9565b61043c5760405162461bcd60e51b815260040180806020018281038252602581526020018061067b6025913960400191505060405180910390fd5b6001546040516001600160a01b03918216918316907fd32d24edea94f55e932d9a008afc425a8561462d1b1f57bc6e508e9a6b9509e190600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600a5481565b60066020526000908152604090208054600182015460028301546003840154600490940154929391926001600160a01b039182169282811692600160a01b90910460ff16911686565b600290565b6001546001600160a01b031690565b60076020526000908152604090205481565b610516610578565b61051f57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b600954600160a01b900463ffffffff1681565b6008602052600090815260409020546001600160a01b031681565b60025481565b6009546001600160a01b031681565b6105d4610578565b6105dd57600080fd5b6105e68161060c565b50565b60006001600160a01b03821661060157506000610607565b50803b15155b919050565b6001600160a01b03811661061f57600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b039290921691909117905556fe44455354494e4154494f4e5f414444524553535f49535f4e4f545f415f434f4e5452414354a265627a7a723158204f0a156c7a5b0c8f2b19d47213adb8e80be82464da678d00feb66a88eb880bd964736f6c63430005110032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ceca73676b6bfed2d7673d131201f733f84b51df000000000000000000000000f486e3b6a432bdd6edaae85a565cd7682a7862bb000000000000000000000000d46042f503b8ec0a166af8c0bfbb0a3c562353f90000000000000000000000007ad7f98f229c5c1ea5161bed952c3007dbe1f307
-----Decoded View---------------
Arg [0] : _proxyTo (address): 0xCeca73676b6bFed2D7673d131201f733f84B51df
Arg [1] : _registry (address): 0xF486e3B6A432Bdd6EDaAe85a565CD7682A7862BB
Arg [2] : _rootChain (address): 0xd46042f503B8Ec0A166af8C0BFbB0a3C562353F9
Arg [3] : _exitNft (address): 0x7ad7f98f229c5C1EA5161bEd952c3007DBE1F307
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000ceca73676b6bfed2d7673d131201f733f84b51df
Arg [1] : 000000000000000000000000f486e3b6a432bdd6edaae85a565cd7682a7862bb
Arg [2] : 000000000000000000000000d46042f503b8ec0a166af8c0bfbb0a3c562353f9
Arg [3] : 0000000000000000000000007ad7f98f229c5c1ea5161bed952c3007dbe1f307
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | Ether (ETH) | 100.00% | $3,420.63 | 0.00001 | $0.034206 |
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.