Ready to simplify your web3 experience? Try the all-in-one web3 app trusted by millions worldwide.
Purchase 100+ cryptocurrencies instantly, with Visa/Mastercard, Google/Apple Pay, and a variety of other funding methods.
Everyday giveaways up to 100 ETH, Lucky Spins. Deposit BONUS 300% and Cashbacks!
9 years old Licensed Crypto Casino, Instant Withdraw 24/7, 6000+ Slots available, Paypal Deposit, Instant Live Support 24/7, 30% Rakeback.
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
5000+ Slots & Live Casino Games, 50+cryptos. Register with Etherscan and get 760% deposit bonus. Win Big$, withdraw it fast.
Play 100s of games anonymously with all major cryptos. Join CryptoWins & start winning!
Anonymous play on awesome games - sign up now for 25 free jackpot spins - worth $100s!
Overview
ETH Balance
Eth Value
$0.00Token Holdings
Could not find any matches!
- ERC-20 Tokens (123)11,680,074.9060506 BREEDBreederDAO (BREED)$176,240.88@0.015147.60647562 cbETHCoinbase Wra... (cbETH)$122,448.14@2,572.0966,900.99040429 RADARDappRadar (RADAR)$296.72@0.0044100 DEPAYDePay (DEPAY)$31.07@0.3107966,159.00620553 DIVIDivi (DIVI)$941.79@0.00112,852.19791247 DOLADola USD Sta... (DOLA)$12,815.06@0.997110,000,000 DUENDEDuende (DUENDE)$873,805.01@0.08747,496,807.22846581 JARVISJARVIS (JARVIS)$364,999.15@0.0487296,738.07742534 KAPKAP Games To... (KAP)$7,961.82@0.0268777 MTRMatter (MTR)$88.57@0.11450.20377581 EUReMonerium EUR... (EURe)$55.44@1.10431,737,200 NFTYNFTY Token (NFTY)$237.42@0.000191,271,820 NOGSNoggles (NOGS)$2,239.45@0.0010,417,291.757621 PEPEPepe (PEPE)$93.44@0.009,711,002.45498726 PINEPine Token (PINE)$28,258.29@0.0029363,914.44235735 POLKPolkamarkets (POLK)$6,253.92@0.01722,000 REVORevomon (REVO)$22.54@0.011317,570,172.5906059 SABAISabai Ecover... (SABAI)$508,103.39@0.028915,917,112.0722973 SAILSAIL Token (SAIL)$67,027.98@0.004213,091,582.663864 KEYSelfKey (KEY)$47,579.39@0.00364,655,349.0362428 TKAITAIKAI Token (TKAI)$34,752.11@0.0075236,848.78034984 TThreshold Ne... (T)$5,380.79@0.02277,930,134.06605919 VABVabble (VAB)$20,699.42@0.00262,993,763.21942413 VLDVALID (VLD)7,519,852,427.90755 VERSEVerse (VERSE)$1,375,381.01@0.0002237,169,527.481412 VRSWVirtuswap To... (VRSW)$172,236.21@0.00070.0048278 wTAOWrapped TAO (wTAO)$2.50@517.3438,342,714.3496345 XENXEN Crypto (XEN)$3.48@0.003,500,001 ZENFZENF Token (ZENF)$13,947.04@0.004552.93555818 MATICMatic Token (MATIC)$209.61@0.379116.82406836 RPLRocket Pool (RPL)$165.55@9.8417,175,553.892 $OT$OPENTOWN1,444,419 ONEPF1point5dao (ONEPF)223,297,003.43587 A3A3A Utility Token$35,649.37@0.0002400,000,000 AKVAkiverse Gov... (AKV)1 asdCRVAladdin sdCR... (asdCRV)34,338.43004945 AEDYArch Ethereu... (AEDY)13,476.4178871 ADDYArch USD Div... (ADDY)223,539,467.636337 RCMArcomia890,508.11242518 AZUKIAzuki (AZUKI)1,344,584 BBCBillionaire ... (BBC)5,979,383.47976913 BILLSBillions Bot (BILLS)1 BFBBlockchain F... (BFB)54,675,336.37111ERC20 ***10 BTRSTBTRST$3.62@0.36211,210.9 bwAJNABurn Wrapped... (bwAJNA)6 CICCCaicaCoin$0.09@0.015213,300.75 C12Carbon 1218 CDYS2CODYS2 (CDYS2)4,000,050 $ECOMCOMEARTH Utility Token1,000,000 COOLCATCoolcat (COOLCA...)1,000,000 COVENCrypto Coven (COVEN)4.04 CTRLCTRL (CTRL)2,028,952.61008583 $TOADSDigiToads ($TOADS)1,000,000 DOODLEDoodle (DOODLE)117.70498789 DFXDummy Fx (DFX)109 DFV1DummyFxV1 (DFV1)275,009.81 DFV4DummyFxV4 (DFV4)3,700,000.81577504 ETLETHEREAL2,500 FXYFloxypay (FXY)2,500,000 GAMEBOYGame Boy (GAMEBO...)3,500,000 GPTGPT Protocol (GPT)3,002,800 HNBHNB Protocol$12,364.42@0.0041100,000,000,000 HBCNHoney Badger... (HBCN)2,105,000 IDGRSIdeagoras (IDGRS)43,596.59274708 IDEASIDEAS10,000,000 IXIIXI (IXI)989,990 JJoule (J)1,198,832.28291102 KNNKNN Token10,000,000 KOOLKoolpeace (KOOL)160 KVXKVX Token1,156 LSDLandscoins (LSD)1,000,000 MUERTOSLos Muertos (MUERTO...)2,075,000,000 LOTTYLotty$460.20@0.001,000,000 MAYCMAYC (MAYC)1,891,480.86288448 MARMchain Token (MAR)1,000,000 MEEBITMeebit (MEEBIT)500,000,000 METODMETA TOY DRA... (METOD)1,000,000 MFERmfer (MFER)1,000,000 MILADYMilady (MILADY)1,000,000 MOONBIRDMoonbird (MOONBI...)1,000,000 MORIEMorie (MORIE)15,122,148.1716667 NESSNESS$548,692.86@0.036383.66154771 NFTENFTEarth822,542.6119754 SHIBNicCageWaluigiElmo42069Inu$48.10@0.00013 NPAYNPAY (NPAY)1,000,000,000 OWNOriginal Wor... (OWN)98.026095 PYUSDPayPal USD$98.01@0.99995,888 PEGGPepeEgg (PEGG)40,000,000,000,000 PEPEGAMEPEPEGAME (PEPEGA...)250 PEPELPpepelp.com (PEPELP)1,000,000 PHANTAPhantabear (PHANTA)500,000,001 PHLPHILCOIN (PHL)10,000,000 PIXELPIXEL (PIXEL)500,000 PRBSPOORBUCKS (PRBS)30,000 ROORealOverOne (ROO)26,230 ReStaMRespawn Stak... (ReStaM)540,703.94439514 RDGRotasDoGarimpo5,000,000 RWARWA.ai (RWA)1,000,000 SNIWSniwToken (SNIW)81,000 SOONSoonSwap$794.24@0.00980 STARStar Token (STAR)1,000,000 SUPDUCKSupDucks (SUPDUC...)450 TAKITaki (TAKI)224,801.1525 TECHTTectone23 (TECHT)1,000 TESTINGTESTING (TESTIN...)400,000,000 TSTTestToken (TST)999,844,314.674206 TETUTetu Token$1,410,750.33@0.0014100,000,000 TMHTMeta:h (TMH)4 TruMATICTruStake MAT... (TruMAT...)6,850.96163328 FUNDUnification$412.30@0.060220,000,000 VDAOViriumDAO (VDAO)1,000,000 WASSIEWassie (WASSIE)12,174,954,354.0787 WENWEN Token$3,141.99@0.0010,000,000 WONWON (WON)1,000,000 GALAXYWoW Galaxy (GALAXY)5 X528X528 (X528)100,900 XFLXFL Token1,000 ☕️☕️coin (☕️)6,969 GIVGiveth$37.35@0.00543,000 LOCGLOCGame$7.11@0.0024168,390,041.12452 SKEBSkeb Coin$128,043.79@0.0008100 TokenERC-20 TOKEN*[Spam]NFT Tokens (9)zsteth.com : airdrop recipient# zsteth.com : airdrop recipientERC-1155claim rewards on pepedao.netpepedao.netERC-1155
More Info
Private Name Tags
ContractCreator
- Transactions
- Internal Transactions
- Token Transfers (ERC-20)
- NFT Transfers
- Contract
- Events
- Analytics
- Multichain Portfolio
- Filter by Tx Type:
- Tx
- Internal Tx
- ERC-20
- NFTs
Latest 25 from a total of 5,046 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Receive Message | 20887909 | 2024-10-03 22:16:47 | 11 hrs ago | 1727993807 | IN | 0 ETH$0.00 | 0.00126585 | 4.2321954 | ||||
Receive Message | 20885443 | 2024-10-03 13:59:47 | 20 hrs ago | 1727963987 | IN | 0 ETH$0.00 | 0.00220432 | 7.38691478 | ||||
Deposit | 20884322 | 2024-10-03 10:14:23 | 23 hrs ago | 1727950463 | IN | 0 ETH$0.00 | 0.00057311 | 6.98278115 | ||||
Deposit | 20883752 | 2024-10-03 8:19:47 | 25 hrs ago | 1727943587 | IN | 0 ETH$0.00 | 0.00104579 | 12.74199835 | ||||
Deposit | 20883654 | 2024-10-03 8:00:11 | 26 hrs ago | 1727942411 | IN | 0 ETH$0.00 | 0.00069067 | 7.69540551 | ||||
Deposit | 20879551 | 2024-10-02 18:17:11 | 39 hrs ago | 1727893031 | IN | 0 ETH$0.00 | 0.00342737 | 40.40615454 | ||||
Deposit | 20876536 | 2024-10-02 8:11:47 | 2 days ago | 1727856707 | IN | 0 ETH$0.00 | 0.00052648 | 6.6968133 | ||||
Deposit | 20875680 | 2024-10-02 5:20:11 | 2 days ago | 1727846411 | IN | 0 ETH$0.00 | 0.00049232 | 5.90386244 | ||||
Deposit | 20871995 | 2024-10-01 17:00:11 | 2 days ago | 1727802011 | IN | 0 ETH$0.00 | 0.00273761 | 32.27443885 | ||||
Receive Message | 20871671 | 2024-10-01 15:54:47 | 2 days ago | 1727798087 | IN | 0 ETH$0.00 | 0.0075776 | 23.50985706 | ||||
Receive Message | 20868920 | 2024-10-01 6:41:47 | 3 days ago | 1727764907 | IN | 0 ETH$0.00 | 0.00450937 | 15.06098317 | ||||
Receive Message | 20868715 | 2024-10-01 6:00:35 | 3 days ago | 1727762435 | IN | 0 ETH$0.00 | 0.0054801 | 17.26669267 | ||||
Deposit | 20867093 | 2024-10-01 0:35:11 | 3 days ago | 1727742911 | IN | 0 ETH$0.00 | 0.00056825 | 7.10398659 | ||||
Deposit | 20866716 | 2024-09-30 23:19:23 | 3 days ago | 1727738363 | IN | 0 ETH$0.00 | 0.0004855 | 6.15957252 | ||||
Deposit | 20865235 | 2024-09-30 18:22:23 | 3 days ago | 1727720543 | IN | 0 ETH$0.00 | 0.00171406 | 20.20757152 | ||||
Deposit | 20864119 | 2024-09-30 14:38:47 | 3 days ago | 1727707127 | IN | 0 ETH$0.00 | 0.0012453 | 15.64633912 | ||||
Receive Message | 20863721 | 2024-09-30 13:18:59 | 3 days ago | 1727702339 | IN | 0 ETH$0.00 | 0.0061414 | 18.94087549 | ||||
Receive Message | 20863713 | 2024-09-30 13:17:23 | 3 days ago | 1727702243 | IN | 0 ETH$0.00 | 0.0130629 | 40.69911016 | ||||
Receive Message | 20863487 | 2024-09-30 12:31:47 | 3 days ago | 1727699507 | IN | 0 ETH$0.00 | 0.00332037 | 10.2668696 | ||||
Deposit | 20863469 | 2024-09-30 12:28:11 | 3 days ago | 1727699291 | IN | 0 ETH$0.00 | 0.00083054 | 10.76578491 | ||||
Deposit | 20860122 | 2024-09-30 1:16:59 | 4 days ago | 1727659019 | IN | 0 ETH$0.00 | 0.0006471 | 7.88433636 | ||||
Receive Message | 20850396 | 2024-09-28 16:41:35 | 5 days ago | 1727541695 | IN | 0 ETH$0.00 | 0.00202846 | 6.61954705 | ||||
Deposit | 20850073 | 2024-09-28 15:36:59 | 5 days ago | 1727537819 | IN | 0 ETH$0.00 | 0.00090125 | 10.04172684 | ||||
Deposit | 20849476 | 2024-09-28 13:37:11 | 5 days ago | 1727530631 | IN | 0 ETH$0.00 | 0.00085983 | 10.13684093 | ||||
Deposit | 20848879 | 2024-09-28 11:37:11 | 5 days ago | 1727523431 | IN | 0 ETH$0.00 | 0.0008316 | 9.2656419 |
View more zero value Internal Transactions in Advanced View mode
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ERC20} from "../../lib/ERC20.sol"; import {Create2} from "../../lib/Create2.sol"; import {IRootChainManager} from "../../lib/IRootChainManager.sol"; import {FxBaseRootTunnel} from "../../tunnel/FxBaseRootTunnel.sol"; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /** * @title FxERC20RootTunnel */ contract FxERC20RootTunnel is FxBaseRootTunnel, Create2 { using SafeERC20 for IERC20; // maybe DEPOSIT and MAP_TOKEN can be reduced to bytes4 bytes32 public constant DEPOSIT = keccak256("DEPOSIT"); bytes32 public constant MAP_TOKEN = keccak256("MAP_TOKEN"); bytes32 public immutable childTokenTemplateCodeHash; IRootChainManager public immutable rootChainManager; event TokenMappedERC20(address indexed rootToken, address indexed childToken); event FxWithdrawERC20( address indexed rootToken, address indexed childToken, address indexed userAddress, uint256 amount ); event FxDepositERC20( address indexed rootToken, address indexed depositor, address indexed userAddress, uint256 amount ); mapping(address => address) public rootToChildTokens; constructor( address _checkpointManager, address _fxRoot, address _fxERC20Token, IRootChainManager _rootChainManager ) FxBaseRootTunnel(_checkpointManager, _fxRoot) { rootChainManager = _rootChainManager; // compute child token template code hash childTokenTemplateCodeHash = keccak256(minimalProxyCreationCode(_fxERC20Token)); } /** * @notice Map a token to enable its movement via the PoS Portal, callable only by mappers * @param rootToken address of token on root chain */ function mapToken(address rootToken) public { // check if token is already mapped require(rootToChildTokens[rootToken] == address(0x0), "FxERC20RootTunnel: ALREADY_MAPPED"); require(rootChainManager.rootToChildToken(rootToken) == address(0x0), "FxERC20RootTunnel: MAPPED_ON_POS"); // name, symbol and decimals ERC20 rootTokenContract = ERC20(rootToken); string memory name = rootTokenContract.name(); string memory symbol = rootTokenContract.symbol(); uint8 decimals = rootTokenContract.decimals(); // MAP_TOKEN, encode(rootToken, name, symbol, decimals) bytes memory message = abi.encode(MAP_TOKEN, abi.encode(rootToken, name, symbol, decimals)); _sendMessageToChild(message); // compute child token address before deployment using create2 bytes32 salt = keccak256(abi.encodePacked(rootToken)); address childToken = computedCreate2Address(salt, childTokenTemplateCodeHash, fxChildTunnel); // add into mapped tokens rootToChildTokens[rootToken] = childToken; emit TokenMappedERC20(rootToken, childToken); } function deposit( address rootToken, address user, uint256 amount, bytes memory data ) public { // map token if not mapped if (rootToChildTokens[rootToken] == address(0x0)) { mapToken(rootToken); } // transfer from depositor to this contract IERC20(rootToken).safeTransferFrom( msg.sender, // depositor address(this), // manager contract amount ); // DEPOSIT, encode(rootToken, depositor, user, amount, extra data) bytes memory message = abi.encode(DEPOSIT, abi.encode(rootToken, msg.sender, user, amount, data)); _sendMessageToChild(message); emit FxDepositERC20(rootToken, msg.sender, user, amount); } // exit processor function _processMessageFromChild(bytes memory data) internal override { (address rootToken, address childToken, address to, uint256 amount) = abi.decode( data, (address, address, address, uint256) ); // validate mapping for root to child require(rootToChildTokens[rootToken] == childToken, "FxERC20RootTunnel: INVALID_MAPPING_ON_EXIT"); // transfer from tokens to IERC20(rootToken).safeTransfer(to, amount); emit FxWithdrawERC20(rootToken, childToken, to, amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "./IERC20.sol"; import {SafeMath} from "./SafeMath.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is IERC20 { using SafeMath for uint256; mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(msg.sender, recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(msg.sender, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve( sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance") ); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve( msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero") ); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } function _setupMetaData( string memory name_, string memory symbol_, uint8 decimals_ ) internal virtual { _name = name_; _symbol = symbol_; _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Create2 adds common methods for minimal proxy with create2 abstract contract Create2 { // creates clone using minimal proxy function createClone(bytes32 _salt, address _target) internal returns (address _result) { bytes20 _targetBytes = bytes20(_target); assembly { let clone := mload(0x40) mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(clone, 0x14), _targetBytes) mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) _result := create2(0, clone, 0x37, _salt) } require(_result != address(0), "Create2: Failed on minimal deploy"); } // get minimal proxy creation code function minimalProxyCreationCode(address logic) internal pure returns (bytes memory) { bytes10 creation = 0x3d602d80600a3d3981f3; bytes10 prefix = 0x363d3d373d3d3d363d73; bytes20 targetBytes = bytes20(logic); bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3; return abi.encodePacked(creation, prefix, targetBytes, suffix); } // get computed create2 address function computedCreate2Address( bytes32 salt, bytes32 bytecodeHash, address deployer ) public pure returns (address) { bytes32 _data = keccak256(abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)); return address(uint160(uint256(_data))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /* * @dev Interace to provide a function from Polygon Root Chain Manager */ interface IRootChainManager { function rootToChildToken(address _rootToken) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {RLPReader} from "../lib/RLPReader.sol"; import {MerklePatriciaProof} from "../lib/MerklePatriciaProof.sol"; import {Merkle} from "../lib/Merkle.sol"; import "../lib/ExitPayloadReader.sol"; interface IFxStateSender { function sendMessageToChild(address _receiver, bytes calldata _data) external; } contract ICheckpointManager { struct HeaderBlock { bytes32 root; uint256 start; uint256 end; uint256 createdAt; address proposer; } /** * @notice mapping of checkpoint header numbers to block details * @dev These checkpoints are submited by plasma contracts */ mapping(uint256 => HeaderBlock) public headerBlocks; } abstract contract FxBaseRootTunnel { using RLPReader for RLPReader.RLPItem; using Merkle for bytes32; using ExitPayloadReader for bytes; using ExitPayloadReader for ExitPayloadReader.ExitPayload; using ExitPayloadReader for ExitPayloadReader.Log; using ExitPayloadReader for ExitPayloadReader.LogTopics; using ExitPayloadReader for ExitPayloadReader.Receipt; // keccak256(MessageSent(bytes)) bytes32 public constant SEND_MESSAGE_EVENT_SIG = 0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036; // state sender contract IFxStateSender public fxRoot; // root chain manager ICheckpointManager public checkpointManager; // child tunnel contract which receives and sends messages address public fxChildTunnel; // storage to avoid duplicate exits mapping(bytes32 => bool) public processedExits; constructor(address _checkpointManager, address _fxRoot) { checkpointManager = ICheckpointManager(_checkpointManager); fxRoot = IFxStateSender(_fxRoot); } // set fxChildTunnel if not set already function setFxChildTunnel(address _fxChildTunnel) public virtual { require(fxChildTunnel == address(0x0), "FxBaseRootTunnel: CHILD_TUNNEL_ALREADY_SET"); fxChildTunnel = _fxChildTunnel; } /** * @notice Send bytes message to Child Tunnel * @param message bytes message that will be sent to Child Tunnel * some message examples - * abi.encode(tokenId); * abi.encode(tokenId, tokenMetadata); * abi.encode(messageType, messageData); */ function _sendMessageToChild(bytes memory message) internal { fxRoot.sendMessageToChild(fxChildTunnel, message); } function _validateAndExtractMessage(bytes memory inputData) internal returns (bytes memory) { ExitPayloadReader.ExitPayload memory payload = inputData.toExitPayload(); bytes memory branchMaskBytes = payload.getBranchMaskAsBytes(); uint256 blockNumber = payload.getBlockNumber(); // checking if exit has already been processed // unique exit is identified using hash of (blockNumber, branchMask, receiptLogIndex) bytes32 exitHash = keccak256( abi.encodePacked( blockNumber, // first 2 nibbles are dropped while generating nibble array // this allows branch masks that are valid but bypass exitHash check (changing first 2 nibbles only) // so converting to nibble array and then hashing it MerklePatriciaProof._getNibbleArray(branchMaskBytes), payload.getReceiptLogIndex() ) ); require(processedExits[exitHash] == false, "FxRootTunnel: EXIT_ALREADY_PROCESSED"); processedExits[exitHash] = true; ExitPayloadReader.Receipt memory receipt = payload.getReceipt(); ExitPayloadReader.Log memory log = receipt.getLog(); // check child tunnel require(fxChildTunnel == log.getEmitter(), "FxRootTunnel: INVALID_FX_CHILD_TUNNEL"); bytes32 receiptRoot = payload.getReceiptRoot(); // verify receipt inclusion require( MerklePatriciaProof.verify(receipt.toBytes(), branchMaskBytes, payload.getReceiptProof(), receiptRoot), "FxRootTunnel: INVALID_RECEIPT_PROOF" ); // verify checkpoint inclusion _checkBlockMembershipInCheckpoint( blockNumber, payload.getBlockTime(), payload.getTxRoot(), receiptRoot, payload.getHeaderNumber(), payload.getBlockProof() ); ExitPayloadReader.LogTopics memory topics = log.getTopics(); require( bytes32(topics.getField(0).toUint()) == SEND_MESSAGE_EVENT_SIG, // topic0 is event sig "FxRootTunnel: INVALID_SIGNATURE" ); // received message data bytes memory message = abi.decode(log.getData(), (bytes)); // event decodes params again, so decoding bytes to get message return message; } function _checkBlockMembershipInCheckpoint( uint256 blockNumber, uint256 blockTime, bytes32 txRoot, bytes32 receiptRoot, uint256 headerNumber, bytes memory blockProof ) private view returns (uint256) { (bytes32 headerRoot, uint256 startBlock, , uint256 createdAt, ) = checkpointManager.headerBlocks(headerNumber); require( keccak256(abi.encodePacked(blockNumber, blockTime, txRoot, receiptRoot)).checkMembership( blockNumber - startBlock, headerRoot, blockProof ), "FxRootTunnel: INVALID_HEADER" ); return createdAt; } /** * @notice receive message from L2 to L1, validated by proof * @dev This function verifies if the transaction actually happened on child chain * * @param inputData RLP encoded data of the reference tx containing following list of fields * 0 - headerNumber - Checkpoint header block number containing the reference tx * 1 - blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root * 2 - blockNumber - Block number containing the reference tx on child chain * 3 - blockTime - Reference tx block time * 4 - txRoot - Transactions root of block * 5 - receiptRoot - Receipts root of block * 6 - receipt - Receipt of the reference transaction * 7 - receiptProof - Merkle proof of the reference receipt * 8 - branchMask - 32 bits denoting the path of receipt in merkle tree * 9 - receiptLogIndex - Log Index to read from the receipt */ function receiveMessage(bytes memory inputData) public virtual { bytes memory message = _validateAndExtractMessage(inputData); _processMessageFromChild(message); } /** * @notice Process message received from Child Tunnel * @dev function needs to be implemented to handle message as per requirement * This is called by onStateReceive function. * Since it is called via a system call, any event will not be emitted during its execution. * @param message bytes message that was sent from Child Tunnel */ function _processMessageFromChild(bytes memory message) internal virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
/* * @author Hamdi Allam [email protected] * Please reach out with any questions or concerns */ pragma solidity ^0.8.0; 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 { uint256 len; uint256 memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint256 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)); uint256 ptr = self.nextPtr; uint256 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) { uint256 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)); uint256 ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } /* * @param item RLP encoded bytes */ function rlpLen(RLPItem memory item) internal pure returns (uint256) { return item.len; } /* * @param item RLP encoded bytes */ function payloadLen(RLPItem memory item) internal pure returns (uint256) { 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)); uint256 items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr); uint256 dataLen; for (uint256 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; uint256 memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } /* * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. * @return keccak256 hash of RLP encoded bytes. */ function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { uint256 ptr = item.memPtr; uint256 len = item.len; bytes32 result; assembly { result := keccak256(ptr, len) } return result; } function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) { uint256 offset = _payloadOffset(item.memPtr); uint256 memPtr = item.memPtr + offset; uint256 len = item.len - offset; // data length return (memPtr, len); } /* * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. * @return keccak256 hash of the item payload. */ function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { (uint256 memPtr, uint256 len) = payloadLocation(item); bytes32 result; assembly { result := keccak256(memPtr, len) } return result; } /** 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; uint256 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); uint256 result; uint256 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(uint160(toUint(item))); } function toUint(RLPItem memory item) internal pure returns (uint256) { require(item.len > 0 && item.len <= 33); uint256 offset = _payloadOffset(item.memPtr); uint256 len = item.len - offset; uint256 result; uint256 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 (uint256) { // one byte prefix require(item.len == 33); uint256 result; uint256 memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); uint256 offset = _payloadOffset(item.memPtr); uint256 len = item.len - offset; // data length bytes memory result = new bytes(len); uint256 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 (uint256) { if (item.len == 0) return 0; uint256 count = 0; uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr); uint256 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(uint256 memPtr) private pure returns (uint256) { uint256 itemLen; uint256 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(uint256 memPtr) private pure returns (uint256) { uint256 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( uint256 src, uint256 dest, uint256 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; } if (len == 0) return; // left over bytes. Mask is used to remove unwanted bytes from the word uint256 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)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {RLPReader} from "./RLPReader.sol"; library MerklePatriciaProof { /* * @dev Verifies a merkle patricia proof. * @param value The terminating value in the trie. * @param encodedPath The path in the trie leading to value. * @param rlpParentNodes The rlp encoded stack of nodes. * @param root The root hash of the trie. * @return The boolean validity of the proof. */ function verify( bytes memory value, bytes memory encodedPath, bytes memory rlpParentNodes, bytes32 root ) internal pure returns (bool) { RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes); RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item); bytes memory currentNode; RLPReader.RLPItem[] memory currentNodeList; bytes32 nodeKey = root; uint256 pathPtr = 0; bytes memory path = _getNibbleArray(encodedPath); if (path.length == 0) { return false; } for (uint256 i = 0; i < parentNodes.length; i++) { if (pathPtr > path.length) { return false; } currentNode = RLPReader.toRlpBytes(parentNodes[i]); if (nodeKey != keccak256(currentNode)) { return false; } currentNodeList = RLPReader.toList(parentNodes[i]); if (currentNodeList.length == 17) { if (pathPtr == path.length) { if (keccak256(RLPReader.toBytes(currentNodeList[16])) == keccak256(value)) { return true; } else { return false; } } uint8 nextPathNibble = uint8(path[pathPtr]); if (nextPathNibble > 16) { return false; } nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[nextPathNibble])); pathPtr += 1; } else if (currentNodeList.length == 2) { uint256 traversed = _nibblesToTraverse(RLPReader.toBytes(currentNodeList[0]), path, pathPtr); if (pathPtr + traversed == path.length) { //leaf node if (keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value)) { return true; } else { return false; } } //extension node if (traversed == 0) { return false; } pathPtr += traversed; nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1])); } else { return false; } } } function _nibblesToTraverse( bytes memory encodedPartialPath, bytes memory path, uint256 pathPtr ) private pure returns (uint256) { uint256 len = 0; // encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath // and slicedPath have elements that are each one hex character (1 nibble) bytes memory partialPath = _getNibbleArray(encodedPartialPath); bytes memory slicedPath = new bytes(partialPath.length); // pathPtr counts nibbles in path // partialPath.length is a number of nibbles for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) { bytes1 pathNibble = path[i]; slicedPath[i - pathPtr] = pathNibble; } if (keccak256(partialPath) == keccak256(slicedPath)) { len = partialPath.length; } else { len = 0; } return len; } // bytes b must be hp encoded function _getNibbleArray(bytes memory b) internal pure returns (bytes memory) { bytes memory nibbles = ""; if (b.length > 0) { uint8 offset; uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b)); if (hpNibble == 1 || hpNibble == 3) { nibbles = new bytes(b.length * 2 - 1); bytes1 oddNibble = _getNthNibbleOfBytes(1, b); nibbles[0] = oddNibble; offset = 1; } else { nibbles = new bytes(b.length * 2 - 2); offset = 0; } for (uint256 i = offset; i < nibbles.length; i++) { nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b); } } return nibbles; } function _getNthNibbleOfBytes(uint256 n, bytes memory str) private pure returns (bytes1) { return bytes1(n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library Merkle { function checkMembership( bytes32 leaf, uint256 index, bytes32 rootHash, bytes memory proof ) internal pure returns (bool) { require(proof.length % 32 == 0, "Invalid proof length"); uint256 proofHeight = proof.length / 32; // Proof of size n means, height of the tree is n+1. // In a tree of height n+1, max #leafs possible is 2 ^ n require(index < 2**proofHeight, "Leaf index is too big"); bytes32 proofElement; bytes32 computedHash = leaf; for (uint256 i = 32; i <= proof.length; i += 32) { assembly { proofElement := mload(add(proof, i)) } if (index % 2 == 0) { computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); } else { computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); } index = index / 2; } return computedHash == rootHash; } }
pragma solidity ^0.8.0; import {RLPReader} from "./RLPReader.sol"; library ExitPayloadReader { using RLPReader for bytes; using RLPReader for RLPReader.RLPItem; uint8 constant WORD_SIZE = 32; struct ExitPayload { RLPReader.RLPItem[] data; } struct Receipt { RLPReader.RLPItem[] data; bytes raw; uint256 logIndex; } struct Log { RLPReader.RLPItem data; RLPReader.RLPItem[] list; } struct LogTopics { RLPReader.RLPItem[] data; } // copy paste of private copy() from RLPReader to avoid changing of existing contracts function copy( uint256 src, uint256 dest, uint256 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 uint256 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)) } } function toExitPayload(bytes memory data) internal pure returns (ExitPayload memory) { RLPReader.RLPItem[] memory payloadData = data.toRlpItem().toList(); return ExitPayload(payloadData); } function getHeaderNumber(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[0].toUint(); } function getBlockProof(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[1].toBytes(); } function getBlockNumber(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[2].toUint(); } function getBlockTime(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[3].toUint(); } function getTxRoot(ExitPayload memory payload) internal pure returns (bytes32) { return bytes32(payload.data[4].toUint()); } function getReceiptRoot(ExitPayload memory payload) internal pure returns (bytes32) { return bytes32(payload.data[5].toUint()); } function getReceipt(ExitPayload memory payload) internal pure returns (Receipt memory receipt) { receipt.raw = payload.data[6].toBytes(); RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem(); if (receiptItem.isList()) { // legacy tx receipt.data = receiptItem.toList(); } else { // pop first byte before parsting receipt bytes memory typedBytes = receipt.raw; bytes memory result = new bytes(typedBytes.length - 1); uint256 srcPtr; uint256 destPtr; assembly { srcPtr := add(33, typedBytes) destPtr := add(0x20, result) } copy(srcPtr, destPtr, result.length); receipt.data = result.toRlpItem().toList(); } receipt.logIndex = getReceiptLogIndex(payload); return receipt; } function getReceiptProof(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[7].toBytes(); } function getBranchMaskAsBytes(ExitPayload memory payload) internal pure returns (bytes memory) { return payload.data[8].toBytes(); } function getBranchMaskAsUint(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[8].toUint(); } function getReceiptLogIndex(ExitPayload memory payload) internal pure returns (uint256) { return payload.data[9].toUint(); } // Receipt methods function toBytes(Receipt memory receipt) internal pure returns (bytes memory) { return receipt.raw; } function getLog(Receipt memory receipt) internal pure returns (Log memory) { RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex]; return Log(logData, logData.toList()); } // Log methods function getEmitter(Log memory log) internal pure returns (address) { return RLPReader.toAddress(log.list[0]); } function getTopics(Log memory log) internal pure returns (LogTopics memory) { return LogTopics(log.list[1].toList()); } function getData(Log memory log) internal pure returns (bytes memory) { return log.list[2].toBytes(); } function toRlpBytes(Log memory log) internal pure returns (bytes memory) { return log.data.toRlpBytes(); } // LogTopics methods function getField(LogTopics memory topics, uint256 index) internal pure returns (RLPReader.RLPItem memory) { return topics.data[index]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "optimizer": { "enabled": true, "runs": 9999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
[{"inputs":[{"internalType":"address","name":"_checkpointManager","type":"address"},{"internalType":"address","name":"_fxRoot","type":"address"},{"internalType":"address","name":"_fxERC20Token","type":"address"},{"internalType":"contract IRootChainManager","name":"_rootChainManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rootToken","type":"address"},{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":true,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FxDepositERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rootToken","type":"address"},{"indexed":true,"internalType":"address","name":"childToken","type":"address"},{"indexed":true,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FxWithdrawERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rootToken","type":"address"},{"indexed":true,"internalType":"address","name":"childToken","type":"address"}],"name":"TokenMappedERC20","type":"event"},{"inputs":[],"name":"DEPOSIT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAP_TOKEN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SEND_MESSAGE_EVENT_SIG","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpointManager","outputs":[{"internalType":"contract ICheckpointManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"childTokenTemplateCodeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes32","name":"bytecodeHash","type":"bytes32"},{"internalType":"address","name":"deployer","type":"address"}],"name":"computedCreate2Address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"rootToken","type":"address"},{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fxChildTunnel","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxRoot","outputs":[{"internalType":"contract IFxStateSender","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rootToken","type":"address"}],"name":"mapToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"processedExits","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"inputData","type":"bytes"}],"name":"receiveMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rootChainManager","outputs":[{"internalType":"contract IRootChainManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rootToChildTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_fxChildTunnel","type":"address"}],"name":"setFxChildTunnel","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b506040516200332b3803806200332b833981016040819052620000349162000103565b600180546001600160a01b038087166001600160a01b03199283161790925560008054928616929091169190911790556001600160601b0319606082901b1660a052620000818262000097565b805160209091012060805250620001c092505050565b604051606090693d602d80600a3d3981f360b01b9069363d3d373d3d3d363d7360b01b9084841b906e5af43d82803e903d91602b57fd5bf360881b90620000e99085908590859085906020016200016a565b604051602081830303815290604052945050505050919050565b6000806000806080858703121562000119578384fd5b84516200012681620001a7565b60208601519094506200013981620001a7565b60408601519093506200014c81620001a7565b60608601519092506200015f81620001a7565b939692955090935050565b6001600160b01b0319948516815292909316600a8301526001600160601b03191660148201526001600160881b0319909116602882015260370190565b6001600160a01b0381168114620001bd57600080fd5b50565b60805160a05160601c613134620001f76000396000818161037f01526105bb01526000818161022c01526108c201526131346000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063aea4e49e11610097578063de9b771f11610066578063de9b771f146101b0578063e9c670ad146101b8578063f4a120f7146101cb578063f953cec7146101de576100f5565b8063aea4e49e14610183578063bd07018d14610198578063c0857ba0146101a0578063d81c8e52146101a8576100f5565b80637337957f116100d35780637337957f14610140578063886a69ba1461016057806388e7006814610168578063972c49281461017b576100f5565b80630e387de6146100fa578063607f2d421461011857806369914b3e14610138575b600080fd5b6101026101f1565b60405161010f919061294e565b60405180910390f35b61012b610126366004612597565b610215565b60405161010f9190612943565b61010261022a565b61015361014e3660046125af565b61024e565b60405161010f91906127ff565b61010261028f565b610153610176366004612483565b6102b3565b6101536102db565b610196610191366004612483565b6102f7565b005b61015361037d565b6101536103a1565b6101026103bd565b6101536103e1565b6101966101c636600461250d565b6103fd565b6101966101d9366004612483565b61054b565b6101966101ec366004612633565b610991565b7f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b03681565b60036020526000908152604090205460ff1681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060ff60f81b83868660405160200161026c9493929190612729565b60408051601f1981840301815291905280516020909101209150505b9392505050565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff16156103365760405162461bcd60e51b815260040161032d90612983565b60405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b7f000000000000000000000000000000000000000000000000000000000000000081565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff84811660009081526004602052604090205416610432576104328461054b565b61045473ffffffffffffffffffffffffffffffffffffffff85163330856109ab565b60007f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8218533868686604051602001610490959493929190612820565b60408051601f19818403018152908290526104ae9291602001612957565b60405160208183030381529060405290506104c881610a36565b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f8a58355ceb4626422a66b0f36743672dde8507c6be664f0e5b9de8350a1321598660405161053c919061294e565b60405180910390a45050505050565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526004602052604090205416156105905760405162461bcd60e51b815260040161032d90612af7565b6040517fea60c7c40000000000000000000000000000000000000000000000000000000081526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063ea60c7c4906106059085906004016127ff565b602060405180830381600087803b15801561061f57600080fd5b505af1158015610633573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610657919061249f565b73ffffffffffffffffffffffffffffffffffffffff161461068a5760405162461bcd60e51b815260040161032d90612c67565b600081905060008173ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b1580156106d757600080fd5b505afa1580156106eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107139190810190612666565b905060008273ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561075d57600080fd5b505afa158015610771573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107999190810190612666565b905060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156107e357600080fd5b505afa1580156107f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081b91906126ac565b905060007f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad8685858560405160200161085794939291906128c7565b60408051601f19818403018152908290526108759291602001612957565b604051602081830303815290604052905061088f81610a36565b6000866040516020016108a291906126f9565b6040516020818303038152906040528051906020012090506000610909827f0000000000000000000000000000000000000000000000000000000000000000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661024e565b73ffffffffffffffffffffffffffffffffffffffff89811660008181526004602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948616948517905551939450919290917fc21cd413746aa9146d86960ed90847c18aa555d8dfd256e0aac3954c41e3cfe291a35050505050505050565b600061099c82610ac7565b90506109a781610cf2565b5050565b610a30846323b872dd60e01b8585856040516024016109cc93929190612867565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610df5565b50505050565b6000546002546040517fb472047700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169263b472047792610a92929116908590600401612898565b600060405180830381600087803b158015610aac57600080fd5b505af1158015610ac0573d6000803e3d6000fd5b5050505050565b60606000610ad483610e96565b90506000610ae182610ec6565b90506000610aee83610f03565b9050600081610afc84610f3a565b610b0586611160565b604051602001610b17939291906127b7565b60408051601f1981840301815291815281516020928301206000818152600390935291205490915060ff1615610b5f5760405162461bcd60e51b815260040161032d90612a3d565b600081815260036020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610b9f8561118a565b90506000610bac82611298565b9050610bb781611327565b60025473ffffffffffffffffffffffffffffffffffffffff908116911614610bf15760405162461bcd60e51b815260040161032d90612d56565b6000610bfc8761135e565b9050610c1a610c0a84611388565b87610c148a61138f565b846113b9565b610c365760405162461bcd60e51b815260040161032d906129e0565b610c6485610c43896116b8565b610c4c8a6116e2565b84610c568c61170c565b610c5f8d611736565b611760565b506000610c708361188e565b90507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036610ca6610ca18360006118d1565b61190b565b14610cc35760405162461bcd60e51b815260040161032d90612bf9565b6000610cce84611986565b806020019051810190610ce19190612666565b99505050505050505050505b919050565b60008060008084806020019051810190610d0c91906124bb565b73ffffffffffffffffffffffffffffffffffffffff8481166000908152600460205260409020549498509296509094509250848116911614610d605760405162461bcd60e51b815260040161032d90612c9c565b610d8173ffffffffffffffffffffffffffffffffffffffff851683836119b0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f1a77c658a097b28097b54b8acb928a569a3830a6cbed2de1f60001c0757eb0d68460405161053c919061294e565b6000610e57826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166119cf9092919063ffffffff16565b805190915015610e915780806020019051810190610e759190612577565b610e915760405162461bcd60e51b815260040161032d90612cf9565b505050565b610e9e612394565b6000610eb1610eac846119de565b611a03565b60408051602081019091529081529392505050565b6060610efd8260000151600881518110610ef057634e487b7160e01b600052603260045260246000fd5b6020026020010151611b29565b92915050565b6000610efd8260000151600281518110610f2d57634e487b7160e01b600052603260045260246000fd5b602002602001015161190b565b60408051602081019091526000815281516060919015610efd57600080610f62600086611bd4565b60f81c90506001811480610f7957508060ff166003145b1561105557600185516002610f8e9190612f85565b610f989190612fc2565b67ffffffffffffffff811115610fbe57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015610fe8576020820181803683370190505b5092506000610ff8600187611bd4565b9050808460008151811061101c57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060019250506110c7565b6002855160026110659190612f85565b61106f9190612fc2565b67ffffffffffffffff81111561109557634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156110bf576020820181803683370190505b509250600091505b60ff82165b8351811015611157576110f66110e560ff851683612fc2565b6110f0906002612e05565b87611bd4565b84828151811061111657634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061114f81613028565b9150506110cc565b50505092915050565b6000610efd8260000151600981518110610f2d57634e487b7160e01b600052603260045260246000fd5b6111926123a7565b6111ba8260000151600681518110610ef057634e487b7160e01b600052603260045260246000fd5b602082018190526000906111cd906119de565b90506111d881611c71565b156111ed576111e681611a03565b8252611284565b6020820151805160009061120390600190612fc2565b67ffffffffffffffff81111561122957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611253576020820181803683370190505b50905060008083602101915082602001905061127182828551611cab565b61127d610eac846119de565b8652505050505b61128d83611160565b604083015250919050565b6112a06123c8565b60006112d783600001516003815181106112ca57634e487b7160e01b600052603260045260246000fd5b6020026020010151611a03565b8360400151815181106112fa57634e487b7160e01b600052603260045260246000fd5b60200260200101519050604051806040016040528082815260200161131e83611a03565b90529392505050565b6000610efd826020015160008151811061135157634e487b7160e01b600052603260045260246000fd5b6020026020010151611d24565b6000610efd8260000151600581518110610f2d57634e487b7160e01b600052603260045260246000fd5b6020015190565b6060610efd8260000151600781518110610ef057634e487b7160e01b600052603260045260246000fd5b6000806113c5846119de565b905060006113d282611a03565b9050606080856000806113e48b610f3a565b90508051600014156114005760009750505050505050506116b0565b60005b86518110156116a7578151831115611426576000985050505050505050506116b0565b61145687828151811061144957634e487b7160e01b600052603260045260246000fd5b6020026020010151611d3e565b955085805190602001208414611477576000985050505050505050506116b0565b61149a8782815181106112ca57634e487b7160e01b600052603260045260246000fd5b945084516011141561159957815183141561150a578c805190602001206114db86601081518110610ef057634e487b7160e01b600052603260045260246000fd5b8051906020012014156114f9576001985050505050505050506116b0565b6000985050505050505050506116b0565b600082848151811061152c57634e487b7160e01b600052603260045260246000fd5b016020015160f81c9050601081111561155157600099505050505050505050506116b0565b611584868260ff168151811061157757634e487b7160e01b600052603260045260246000fd5b6020026020010151611dcd565b9450611591600185612e05565b935050611695565b8451600214156114f95760006115d36115cc87600081518110610ef057634e487b7160e01b600052603260045260246000fd5b8486611dfb565b83519091506115e28286612e05565b1415611645578d8051906020012061161487600181518110610ef057634e487b7160e01b600052603260045260246000fd5b80519060200120141561163357600199505050505050505050506116b0565b600099505050505050505050506116b0565b8061165c57600099505050505050505050506116b0565b6116668185612e05565b935061168c8660018151811061157757634e487b7160e01b600052603260045260246000fd5b94506116959050565b8061169f81613028565b915050611403565b50505050505050505b949350505050565b6000610efd8260000151600381518110610f2d57634e487b7160e01b600052603260045260246000fd5b6000610efd8260000151600481518110610f2d57634e487b7160e01b600052603260045260246000fd5b6000610efd8260000151600081518110610f2d57634e487b7160e01b600052603260045260246000fd5b6060610efd8260000151600181518110610ef057634e487b7160e01b600052603260045260246000fd5b6001546040517f41539d4a00000000000000000000000000000000000000000000000000000000815260009182918291829173ffffffffffffffffffffffffffffffffffffffff909116906341539d4a906117bf90899060040161294e565b60a06040518083038186803b1580156117d757600080fd5b505afa1580156117eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180f91906125e7565b5093505092509250611865828b6118269190612fc2565b84878d8d8d8d60405160200161183f94939291906127e4565b60405160208183030381529060405280519060200120611f5e909392919063ffffffff16565b6118815760405162461bcd60e51b815260040161032d90612bc2565b9998505050505050505050565b611896612394565b60405180602001604052806118c984602001516001815181106112ca57634e487b7160e01b600052603260045260246000fd5b905292915050565b6118d96123e8565b82518051839081106118fb57634e487b7160e01b600052603260045260246000fd5b6020026020010151905092915050565b80516000901580159061192057508151602110155b61192957600080fd5b60006119388360200151612072565b9050600081846000015161194c9190612fc2565b90506000808386602001516119619190612e05565b905080519150602083101561197d57826020036101000a820491505b50949350505050565b6060610efd8260200151600281518110610ef057634e487b7160e01b600052603260045260246000fd5b610e918363a9059cbb60e01b84846040516024016109cc92919061291d565b60606116b084846000856120f7565b6119e66123e8565b506040805180820190915281518152602082810190820152919050565b6060611a0e82611c71565b611a1757600080fd5b6000611a22836121c4565b905060008167ffffffffffffffff811115611a4d57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611a8657816020015b611a736123e8565b815260200190600190039081611a6b5790505b5090506000611a988560200151612072565b8560200151611aa79190612e05565b90506000805b84811015611b1e57611abe83612247565b9150604051806040016040528083815260200184815250848281518110611af557634e487b7160e01b600052603260045260246000fd5b6020908102919091010152611b0a8284612e05565b925080611b1681613028565b915050611aad565b509195945050505050565b8051606090611b3757600080fd5b6000611b468360200151612072565b90506000818460000151611b5a9190612fc2565b905060008167ffffffffffffffff811115611b8557634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611baf576020820181803683370190505b509050600081602001905061197d848760200151611bcd9190612e05565b8285612309565b6000611be1600284613061565b15611c2957601082611bf4600286612e1d565b81518110611c1257634e487b7160e01b600052603260045260246000fd5b0160200151611c24919060f81c613075565b611c67565b601082611c37600286612e1d565b81518110611c5557634e487b7160e01b600052603260045260246000fd5b0160200151611c67919060f81c612e31565b60f81b9392505050565b8051600090611c8257506000610ced565b6020820151805160001a9060c0821015611ca157600092505050610ced565b5060019392505050565b80611cb557610e91565b60208110611ced5782518252611ccc602084612e05565b9250611cd9602083612e05565b9150611ce6602082612fc2565b9050611cb5565b60006001611cfc836020612fc2565b611d0890610100612e99565b611d129190612fc2565b84518451821691191617835250505050565b8051600090601514611d3557600080fd5b610efd8261190b565b60606000826000015167ffffffffffffffff811115611d6d57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611d97576020820181803683370190505b509050805160001415611dab579050610ced565b6000816020019050611dc68460200151828660000151612309565b5092915050565b8051600090602114611dde57600080fd5b60008083602001516001611df29190612e05565b51949350505050565b60008080611e0886610f3a565b90506000815167ffffffffffffffff811115611e3457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611e5e576020820181803683370190505b509050845b8251611e6f9087612e05565b811015611f2e576000878281518110611e9857634e487b7160e01b600052603260045260246000fd5b01602001517fff000000000000000000000000000000000000000000000000000000000000001690508083611ecd8985612fc2565b81518110611eeb57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350508080611f2690613028565b915050611e63565b50808051906020012082805190602001201415611f4e5781519250611f53565b600092505b509095945050505050565b600060208251611f6e9190613061565b15611f8b5760405162461bcd60e51b815260040161032d90612b54565b600060208351611f9b9190612e1d565b9050611fa8816002612e99565b8510611fc65760405162461bcd60e51b815260040161032d90612b8b565b60008660205b8551811161206457858101519250611fe5600289613061565b612019578183604051602001611ffc92919061278d565b604051602081830303815290604052805190602001209150612045565b828260405160200161202c92919061278d565b6040516020818303038152906040528051906020012091505b612050600289612e1d565b975061205d602082612e05565b9050611fcc565b509094149695505050505050565b8051600090811a608081101561208c576000915050610ced565b60b88110806120a7575060c081108015906120a7575060f881105b156120b6576001915050610ced565b60c08110156120eb576120cb600160b8612fd9565b6120d89060ff1682612fc2565b6120e3906001612e05565b915050610ced565b6120cb600160f8612fd9565b6060824710156121195760405162461bcd60e51b815260040161032d90612a9a565b61212285612355565b61213e5760405162461bcd60e51b815260040161032d90612c30565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612167919061279b565b60006040518083038185875af1925050503d80600081146121a4576040519150601f19603f3d011682016040523d82523d6000602084013e6121a9565b606091505b50915091506121b982828661235b565b979650505050505050565b80516000906121d557506000610ced565b6000806121e58460200151612072565b84602001516121f49190612e05565b905060008460000151856020015161220c9190612e05565b90505b8082101561223e5761222082612247565b61222a9083612e05565b91508261223681613028565b93505061220f565b50909392505050565b80516000908190811a60808110156122625760019150611dc6565b60b881101561228857612276608082612fc2565b612281906001612e05565b9150611dc6565b60c08110156122b55760b78103600185019450806020036101000a85510460018201810193505050611dc6565b60f88110156122c95761227660c082612fc2565b60019390930151602084900360f7016101000a90049092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a0192915050565b8061231357610e91565b6020811061234b578251825261232a602084612e05565b9250612337602083612e05565b9150612344602082612fc2565b9050612313565b80611ced57610e91565b3b151590565b6060831561236a575081610288565b82511561237a5782518084602001fd5b8160405162461bcd60e51b815260040161032d9190612970565b6040518060200160405280606081525090565b60405180606001604052806060815260200160608152602001600081525090565b60405180604001604052806123db6123e8565b8152602001606081525090565b604051806040016040528060008152602001600081525090565b600061241561241084612ddd565b612db3565b905082815283838301111561242957600080fd5b610288836020830184612ffc565b600082601f830112612447578081fd5b813561245561241082612ddd565b818152846020838601011115612469578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215612494578081fd5b8135610288816130d9565b6000602082840312156124b0578081fd5b8151610288816130d9565b600080600080608085870312156124d0578283fd5b84516124db816130d9565b60208601519094506124ec816130d9565b60408601519093506124fd816130d9565b6060959095015193969295505050565b60008060008060808587031215612522578384fd5b843561252d816130d9565b9350602085013561253d816130d9565b925060408501359150606085013567ffffffffffffffff81111561255f578182fd5b61256b87828801612437565b91505092959194509250565b600060208284031215612588578081fd5b81518015158114610288578182fd5b6000602082840312156125a8578081fd5b5035919050565b6000806000606084860312156125c3578283fd5b833592506020840135915060408401356125dc816130d9565b809150509250925092565b600080600080600060a086880312156125fe578081fd5b855194506020860151935060408601519250606086015191506080860151612625816130d9565b809150509295509295909350565b600060208284031215612644578081fd5b813567ffffffffffffffff81111561265a578182fd5b6116b084828501612437565b600060208284031215612677578081fd5b815167ffffffffffffffff81111561268d578182fd5b8201601f8101841361269d578182fd5b6116b084825160208401612402565b6000602082840312156126bd578081fd5b815160ff81168114610288578182fd5b600081518084526126e5816020860160208601612ffc565b601f01601f19169290920160200192915050565b60609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b7fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b918252602082015260400190565b600082516127ad818460208701612ffc565b9190910192915050565b600084825283516127cf816020850160208801612ffc565b60209201918201929092526040019392505050565b93845260208401929092526040830152606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352808716602084015280861660408401525083606083015260a060808301526121b960a08301846126cd565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b600073ffffffffffffffffffffffffffffffffffffffff84168252604060208301526116b060408301846126cd565b600073ffffffffffffffffffffffffffffffffffffffff86168252608060208301526128f660808301866126cd565b828103604084015261290881866126cd565b91505060ff8316606083015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b901515815260200190565b90815260200190565b6000838252604060208301526116b060408301846126cd565b60006020825261028860208301846126cd565b6020808252602a908201527f467842617365526f6f7454756e6e656c3a204348494c445f54554e4e454c5f4160408201527f4c52454144595f53455400000000000000000000000000000000000000000000606082015260800190565b60208082526023908201527f4678526f6f7454756e6e656c3a20494e56414c49445f524543454950545f505260408201527f4f4f460000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4678526f6f7454756e6e656c3a20455849545f414c52454144595f50524f434560408201527f5353454400000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f46784552433230526f6f7454756e6e656c3a20414c52454144595f4d4150504560408201527f4400000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f496e76616c69642070726f6f66206c656e677468000000000000000000000000604082015260600190565b60208082526015908201527f4c65616620696e64657820697320746f6f206269670000000000000000000000604082015260600190565b6020808252601c908201527f4678526f6f7454756e6e656c3a20494e56414c49445f48454144455200000000604082015260600190565b6020808252601f908201527f4678526f6f7454756e6e656c3a20494e56414c49445f5349474e415455524500604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252818101527f46784552433230526f6f7454756e6e656c3a204d41505045445f4f4e5f504f53604082015260600190565b6020808252602a908201527f46784552433230526f6f7454756e6e656c3a20494e56414c49445f4d4150504960408201527f4e475f4f4e5f4558495400000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b60208082526025908201527f4678526f6f7454756e6e656c3a20494e56414c49445f46585f4348494c445f5460408201527f554e4e454c000000000000000000000000000000000000000000000000000000606082015260800190565b60405181810167ffffffffffffffff81118282101715612dd557612dd56130c3565b604052919050565b600067ffffffffffffffff821115612df757612df76130c3565b50601f01601f191660200190565b60008219821115612e1857612e18613097565b500190565b600082612e2c57612e2c6130ad565b500490565b600060ff831680612e4457612e446130ad565b8060ff84160491505092915050565b80825b6001808611612e655750612e90565b818704821115612e7757612e77613097565b80861615612e8457918102915b9490941c938002612e56565b94509492505050565b60006102887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484600082612ed057506001610288565b81612edd57506000610288565b8160018114612ef35760028114612efd57612f2a565b6001915050610288565b60ff841115612f0e57612f0e613097565b6001841b915084821115612f2457612f24613097565b50610288565b5060208310610133831016604e8410600b8410161715612f5d575081810a83811115612f5857612f58613097565b610288565b612f6a8484846001612e53565b808604821115612f7c57612f7c613097565b02949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612fbd57612fbd613097565b500290565b600082821015612fd457612fd4613097565b500390565b600060ff821660ff841680821015612ff357612ff3613097565b90039392505050565b60005b83811015613017578181015183820152602001612fff565b83811115610a305750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561305a5761305a613097565b5060010190565b600082613070576130706130ad565b500690565b600060ff831680613088576130886130ad565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146130fb57600080fd5b5056fea2646970667358221220607c4bf60f62fb1d05276fce640c1e0d46510eeefc3dfe37164a02c39de3f85f64736f6c6343000800003300000000000000000000000086e4dc95c7fbdbf52e33d563bbdb00823894c287000000000000000000000000fe5e5d361b2ad62c541bab87c45a0b9b018389a2000000000000000000000000ad87e3b217c66b0d45deafbc540330d300811b94000000000000000000000000a0c68c638235ee32657e8f720a23cec1bfc77c77
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100f55760003560e01c8063aea4e49e11610097578063de9b771f11610066578063de9b771f146101b0578063e9c670ad146101b8578063f4a120f7146101cb578063f953cec7146101de576100f5565b8063aea4e49e14610183578063bd07018d14610198578063c0857ba0146101a0578063d81c8e52146101a8576100f5565b80637337957f116100d35780637337957f14610140578063886a69ba1461016057806388e7006814610168578063972c49281461017b576100f5565b80630e387de6146100fa578063607f2d421461011857806369914b3e14610138575b600080fd5b6101026101f1565b60405161010f919061294e565b60405180910390f35b61012b610126366004612597565b610215565b60405161010f9190612943565b61010261022a565b61015361014e3660046125af565b61024e565b60405161010f91906127ff565b61010261028f565b610153610176366004612483565b6102b3565b6101536102db565b610196610191366004612483565b6102f7565b005b61015361037d565b6101536103a1565b6101026103bd565b6101536103e1565b6101966101c636600461250d565b6103fd565b6101966101d9366004612483565b61054b565b6101966101ec366004612633565b610991565b7f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b03681565b60036020526000908152604090205460ff1681565b7f74142732439706f04e753eb52ab5ec44c1f97d3b6627a09e2f5a6115516df80381565b60008060ff60f81b83868660405160200161026c9493929190612729565b60408051601f1981840301815291905280516020909101209150505b9392505050565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60025473ffffffffffffffffffffffffffffffffffffffff16156103365760405162461bcd60e51b815260040161032d90612983565b60405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b7f000000000000000000000000a0c68c638235ee32657e8f720a23cec1bfc77c7781565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff84811660009081526004602052604090205416610432576104328461054b565b61045473ffffffffffffffffffffffffffffffffffffffff85163330856109ab565b60007f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8218533868686604051602001610490959493929190612820565b60408051601f19818403018152908290526104ae9291602001612957565b60405160208183030381529060405290506104c881610a36565b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f8a58355ceb4626422a66b0f36743672dde8507c6be664f0e5b9de8350a1321598660405161053c919061294e565b60405180910390a45050505050565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526004602052604090205416156105905760405162461bcd60e51b815260040161032d90612af7565b6040517fea60c7c40000000000000000000000000000000000000000000000000000000081526000907f000000000000000000000000a0c68c638235ee32657e8f720a23cec1bfc77c7773ffffffffffffffffffffffffffffffffffffffff169063ea60c7c4906106059085906004016127ff565b602060405180830381600087803b15801561061f57600080fd5b505af1158015610633573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610657919061249f565b73ffffffffffffffffffffffffffffffffffffffff161461068a5760405162461bcd60e51b815260040161032d90612c67565b600081905060008173ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b1580156106d757600080fd5b505afa1580156106eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107139190810190612666565b905060008273ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561075d57600080fd5b505afa158015610771573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107999190810190612666565b905060008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156107e357600080fd5b505afa1580156107f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081b91906126ac565b905060007f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad8685858560405160200161085794939291906128c7565b60408051601f19818403018152908290526108759291602001612957565b604051602081830303815290604052905061088f81610a36565b6000866040516020016108a291906126f9565b6040516020818303038152906040528051906020012090506000610909827f74142732439706f04e753eb52ab5ec44c1f97d3b6627a09e2f5a6115516df803600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661024e565b73ffffffffffffffffffffffffffffffffffffffff89811660008181526004602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948616948517905551939450919290917fc21cd413746aa9146d86960ed90847c18aa555d8dfd256e0aac3954c41e3cfe291a35050505050505050565b600061099c82610ac7565b90506109a781610cf2565b5050565b610a30846323b872dd60e01b8585856040516024016109cc93929190612867565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152610df5565b50505050565b6000546002546040517fb472047700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169263b472047792610a92929116908590600401612898565b600060405180830381600087803b158015610aac57600080fd5b505af1158015610ac0573d6000803e3d6000fd5b5050505050565b60606000610ad483610e96565b90506000610ae182610ec6565b90506000610aee83610f03565b9050600081610afc84610f3a565b610b0586611160565b604051602001610b17939291906127b7565b60408051601f1981840301815291815281516020928301206000818152600390935291205490915060ff1615610b5f5760405162461bcd60e51b815260040161032d90612a3d565b600081815260036020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610b9f8561118a565b90506000610bac82611298565b9050610bb781611327565b60025473ffffffffffffffffffffffffffffffffffffffff908116911614610bf15760405162461bcd60e51b815260040161032d90612d56565b6000610bfc8761135e565b9050610c1a610c0a84611388565b87610c148a61138f565b846113b9565b610c365760405162461bcd60e51b815260040161032d906129e0565b610c6485610c43896116b8565b610c4c8a6116e2565b84610c568c61170c565b610c5f8d611736565b611760565b506000610c708361188e565b90507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036610ca6610ca18360006118d1565b61190b565b14610cc35760405162461bcd60e51b815260040161032d90612bf9565b6000610cce84611986565b806020019051810190610ce19190612666565b99505050505050505050505b919050565b60008060008084806020019051810190610d0c91906124bb565b73ffffffffffffffffffffffffffffffffffffffff8481166000908152600460205260409020549498509296509094509250848116911614610d605760405162461bcd60e51b815260040161032d90612c9c565b610d8173ffffffffffffffffffffffffffffffffffffffff851683836119b0565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f1a77c658a097b28097b54b8acb928a569a3830a6cbed2de1f60001c0757eb0d68460405161053c919061294e565b6000610e57826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166119cf9092919063ffffffff16565b805190915015610e915780806020019051810190610e759190612577565b610e915760405162461bcd60e51b815260040161032d90612cf9565b505050565b610e9e612394565b6000610eb1610eac846119de565b611a03565b60408051602081019091529081529392505050565b6060610efd8260000151600881518110610ef057634e487b7160e01b600052603260045260246000fd5b6020026020010151611b29565b92915050565b6000610efd8260000151600281518110610f2d57634e487b7160e01b600052603260045260246000fd5b602002602001015161190b565b60408051602081019091526000815281516060919015610efd57600080610f62600086611bd4565b60f81c90506001811480610f7957508060ff166003145b1561105557600185516002610f8e9190612f85565b610f989190612fc2565b67ffffffffffffffff811115610fbe57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015610fe8576020820181803683370190505b5092506000610ff8600187611bd4565b9050808460008151811061101c57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060019250506110c7565b6002855160026110659190612f85565b61106f9190612fc2565b67ffffffffffffffff81111561109557634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156110bf576020820181803683370190505b509250600091505b60ff82165b8351811015611157576110f66110e560ff851683612fc2565b6110f0906002612e05565b87611bd4565b84828151811061111657634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061114f81613028565b9150506110cc565b50505092915050565b6000610efd8260000151600981518110610f2d57634e487b7160e01b600052603260045260246000fd5b6111926123a7565b6111ba8260000151600681518110610ef057634e487b7160e01b600052603260045260246000fd5b602082018190526000906111cd906119de565b90506111d881611c71565b156111ed576111e681611a03565b8252611284565b6020820151805160009061120390600190612fc2565b67ffffffffffffffff81111561122957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611253576020820181803683370190505b50905060008083602101915082602001905061127182828551611cab565b61127d610eac846119de565b8652505050505b61128d83611160565b604083015250919050565b6112a06123c8565b60006112d783600001516003815181106112ca57634e487b7160e01b600052603260045260246000fd5b6020026020010151611a03565b8360400151815181106112fa57634e487b7160e01b600052603260045260246000fd5b60200260200101519050604051806040016040528082815260200161131e83611a03565b90529392505050565b6000610efd826020015160008151811061135157634e487b7160e01b600052603260045260246000fd5b6020026020010151611d24565b6000610efd8260000151600581518110610f2d57634e487b7160e01b600052603260045260246000fd5b6020015190565b6060610efd8260000151600781518110610ef057634e487b7160e01b600052603260045260246000fd5b6000806113c5846119de565b905060006113d282611a03565b9050606080856000806113e48b610f3a565b90508051600014156114005760009750505050505050506116b0565b60005b86518110156116a7578151831115611426576000985050505050505050506116b0565b61145687828151811061144957634e487b7160e01b600052603260045260246000fd5b6020026020010151611d3e565b955085805190602001208414611477576000985050505050505050506116b0565b61149a8782815181106112ca57634e487b7160e01b600052603260045260246000fd5b945084516011141561159957815183141561150a578c805190602001206114db86601081518110610ef057634e487b7160e01b600052603260045260246000fd5b8051906020012014156114f9576001985050505050505050506116b0565b6000985050505050505050506116b0565b600082848151811061152c57634e487b7160e01b600052603260045260246000fd5b016020015160f81c9050601081111561155157600099505050505050505050506116b0565b611584868260ff168151811061157757634e487b7160e01b600052603260045260246000fd5b6020026020010151611dcd565b9450611591600185612e05565b935050611695565b8451600214156114f95760006115d36115cc87600081518110610ef057634e487b7160e01b600052603260045260246000fd5b8486611dfb565b83519091506115e28286612e05565b1415611645578d8051906020012061161487600181518110610ef057634e487b7160e01b600052603260045260246000fd5b80519060200120141561163357600199505050505050505050506116b0565b600099505050505050505050506116b0565b8061165c57600099505050505050505050506116b0565b6116668185612e05565b935061168c8660018151811061157757634e487b7160e01b600052603260045260246000fd5b94506116959050565b8061169f81613028565b915050611403565b50505050505050505b949350505050565b6000610efd8260000151600381518110610f2d57634e487b7160e01b600052603260045260246000fd5b6000610efd8260000151600481518110610f2d57634e487b7160e01b600052603260045260246000fd5b6000610efd8260000151600081518110610f2d57634e487b7160e01b600052603260045260246000fd5b6060610efd8260000151600181518110610ef057634e487b7160e01b600052603260045260246000fd5b6001546040517f41539d4a00000000000000000000000000000000000000000000000000000000815260009182918291829173ffffffffffffffffffffffffffffffffffffffff909116906341539d4a906117bf90899060040161294e565b60a06040518083038186803b1580156117d757600080fd5b505afa1580156117eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180f91906125e7565b5093505092509250611865828b6118269190612fc2565b84878d8d8d8d60405160200161183f94939291906127e4565b60405160208183030381529060405280519060200120611f5e909392919063ffffffff16565b6118815760405162461bcd60e51b815260040161032d90612bc2565b9998505050505050505050565b611896612394565b60405180602001604052806118c984602001516001815181106112ca57634e487b7160e01b600052603260045260246000fd5b905292915050565b6118d96123e8565b82518051839081106118fb57634e487b7160e01b600052603260045260246000fd5b6020026020010151905092915050565b80516000901580159061192057508151602110155b61192957600080fd5b60006119388360200151612072565b9050600081846000015161194c9190612fc2565b90506000808386602001516119619190612e05565b905080519150602083101561197d57826020036101000a820491505b50949350505050565b6060610efd8260200151600281518110610ef057634e487b7160e01b600052603260045260246000fd5b610e918363a9059cbb60e01b84846040516024016109cc92919061291d565b60606116b084846000856120f7565b6119e66123e8565b506040805180820190915281518152602082810190820152919050565b6060611a0e82611c71565b611a1757600080fd5b6000611a22836121c4565b905060008167ffffffffffffffff811115611a4d57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611a8657816020015b611a736123e8565b815260200190600190039081611a6b5790505b5090506000611a988560200151612072565b8560200151611aa79190612e05565b90506000805b84811015611b1e57611abe83612247565b9150604051806040016040528083815260200184815250848281518110611af557634e487b7160e01b600052603260045260246000fd5b6020908102919091010152611b0a8284612e05565b925080611b1681613028565b915050611aad565b509195945050505050565b8051606090611b3757600080fd5b6000611b468360200151612072565b90506000818460000151611b5a9190612fc2565b905060008167ffffffffffffffff811115611b8557634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611baf576020820181803683370190505b509050600081602001905061197d848760200151611bcd9190612e05565b8285612309565b6000611be1600284613061565b15611c2957601082611bf4600286612e1d565b81518110611c1257634e487b7160e01b600052603260045260246000fd5b0160200151611c24919060f81c613075565b611c67565b601082611c37600286612e1d565b81518110611c5557634e487b7160e01b600052603260045260246000fd5b0160200151611c67919060f81c612e31565b60f81b9392505050565b8051600090611c8257506000610ced565b6020820151805160001a9060c0821015611ca157600092505050610ced565b5060019392505050565b80611cb557610e91565b60208110611ced5782518252611ccc602084612e05565b9250611cd9602083612e05565b9150611ce6602082612fc2565b9050611cb5565b60006001611cfc836020612fc2565b611d0890610100612e99565b611d129190612fc2565b84518451821691191617835250505050565b8051600090601514611d3557600080fd5b610efd8261190b565b60606000826000015167ffffffffffffffff811115611d6d57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611d97576020820181803683370190505b509050805160001415611dab579050610ced565b6000816020019050611dc68460200151828660000151612309565b5092915050565b8051600090602114611dde57600080fd5b60008083602001516001611df29190612e05565b51949350505050565b60008080611e0886610f3a565b90506000815167ffffffffffffffff811115611e3457634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611e5e576020820181803683370190505b509050845b8251611e6f9087612e05565b811015611f2e576000878281518110611e9857634e487b7160e01b600052603260045260246000fd5b01602001517fff000000000000000000000000000000000000000000000000000000000000001690508083611ecd8985612fc2565b81518110611eeb57634e487b7160e01b600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350508080611f2690613028565b915050611e63565b50808051906020012082805190602001201415611f4e5781519250611f53565b600092505b509095945050505050565b600060208251611f6e9190613061565b15611f8b5760405162461bcd60e51b815260040161032d90612b54565b600060208351611f9b9190612e1d565b9050611fa8816002612e99565b8510611fc65760405162461bcd60e51b815260040161032d90612b8b565b60008660205b8551811161206457858101519250611fe5600289613061565b612019578183604051602001611ffc92919061278d565b604051602081830303815290604052805190602001209150612045565b828260405160200161202c92919061278d565b6040516020818303038152906040528051906020012091505b612050600289612e1d565b975061205d602082612e05565b9050611fcc565b509094149695505050505050565b8051600090811a608081101561208c576000915050610ced565b60b88110806120a7575060c081108015906120a7575060f881105b156120b6576001915050610ced565b60c08110156120eb576120cb600160b8612fd9565b6120d89060ff1682612fc2565b6120e3906001612e05565b915050610ced565b6120cb600160f8612fd9565b6060824710156121195760405162461bcd60e51b815260040161032d90612a9a565b61212285612355565b61213e5760405162461bcd60e51b815260040161032d90612c30565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612167919061279b565b60006040518083038185875af1925050503d80600081146121a4576040519150601f19603f3d011682016040523d82523d6000602084013e6121a9565b606091505b50915091506121b982828661235b565b979650505050505050565b80516000906121d557506000610ced565b6000806121e58460200151612072565b84602001516121f49190612e05565b905060008460000151856020015161220c9190612e05565b90505b8082101561223e5761222082612247565b61222a9083612e05565b91508261223681613028565b93505061220f565b50909392505050565b80516000908190811a60808110156122625760019150611dc6565b60b881101561228857612276608082612fc2565b612281906001612e05565b9150611dc6565b60c08110156122b55760b78103600185019450806020036101000a85510460018201810193505050611dc6565b60f88110156122c95761227660c082612fc2565b60019390930151602084900360f7016101000a90049092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0a0192915050565b8061231357610e91565b6020811061234b578251825261232a602084612e05565b9250612337602083612e05565b9150612344602082612fc2565b9050612313565b80611ced57610e91565b3b151590565b6060831561236a575081610288565b82511561237a5782518084602001fd5b8160405162461bcd60e51b815260040161032d9190612970565b6040518060200160405280606081525090565b60405180606001604052806060815260200160608152602001600081525090565b60405180604001604052806123db6123e8565b8152602001606081525090565b604051806040016040528060008152602001600081525090565b600061241561241084612ddd565b612db3565b905082815283838301111561242957600080fd5b610288836020830184612ffc565b600082601f830112612447578081fd5b813561245561241082612ddd565b818152846020838601011115612469578283fd5b816020850160208301379081016020019190915292915050565b600060208284031215612494578081fd5b8135610288816130d9565b6000602082840312156124b0578081fd5b8151610288816130d9565b600080600080608085870312156124d0578283fd5b84516124db816130d9565b60208601519094506124ec816130d9565b60408601519093506124fd816130d9565b6060959095015193969295505050565b60008060008060808587031215612522578384fd5b843561252d816130d9565b9350602085013561253d816130d9565b925060408501359150606085013567ffffffffffffffff81111561255f578182fd5b61256b87828801612437565b91505092959194509250565b600060208284031215612588578081fd5b81518015158114610288578182fd5b6000602082840312156125a8578081fd5b5035919050565b6000806000606084860312156125c3578283fd5b833592506020840135915060408401356125dc816130d9565b809150509250925092565b600080600080600060a086880312156125fe578081fd5b855194506020860151935060408601519250606086015191506080860151612625816130d9565b809150509295509295909350565b600060208284031215612644578081fd5b813567ffffffffffffffff81111561265a578182fd5b6116b084828501612437565b600060208284031215612677578081fd5b815167ffffffffffffffff81111561268d578182fd5b8201601f8101841361269d578182fd5b6116b084825160208401612402565b6000602082840312156126bd578081fd5b815160ff81168114610288578182fd5b600081518084526126e5816020860160208601612ffc565b601f01601f19169290920160200192915050565b60609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b7fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b918252602082015260400190565b600082516127ad818460208701612ffc565b9190910192915050565b600084825283516127cf816020850160208801612ffc565b60209201918201929092526040019392505050565b93845260208401929092526040830152606082015260800190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8088168352808716602084015280861660408401525083606083015260a060808301526121b960a08301846126cd565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b600073ffffffffffffffffffffffffffffffffffffffff84168252604060208301526116b060408301846126cd565b600073ffffffffffffffffffffffffffffffffffffffff86168252608060208301526128f660808301866126cd565b828103604084015261290881866126cd565b91505060ff8316606083015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b901515815260200190565b90815260200190565b6000838252604060208301526116b060408301846126cd565b60006020825261028860208301846126cd565b6020808252602a908201527f467842617365526f6f7454756e6e656c3a204348494c445f54554e4e454c5f4160408201527f4c52454144595f53455400000000000000000000000000000000000000000000606082015260800190565b60208082526023908201527f4678526f6f7454756e6e656c3a20494e56414c49445f524543454950545f505260408201527f4f4f460000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4678526f6f7454756e6e656c3a20455849545f414c52454144595f50524f434560408201527f5353454400000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f46784552433230526f6f7454756e6e656c3a20414c52454144595f4d4150504560408201527f4400000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526014908201527f496e76616c69642070726f6f66206c656e677468000000000000000000000000604082015260600190565b60208082526015908201527f4c65616620696e64657820697320746f6f206269670000000000000000000000604082015260600190565b6020808252601c908201527f4678526f6f7454756e6e656c3a20494e56414c49445f48454144455200000000604082015260600190565b6020808252601f908201527f4678526f6f7454756e6e656c3a20494e56414c49445f5349474e415455524500604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252818101527f46784552433230526f6f7454756e6e656c3a204d41505045445f4f4e5f504f53604082015260600190565b6020808252602a908201527f46784552433230526f6f7454756e6e656c3a20494e56414c49445f4d4150504960408201527f4e475f4f4e5f4558495400000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b60208082526025908201527f4678526f6f7454756e6e656c3a20494e56414c49445f46585f4348494c445f5460408201527f554e4e454c000000000000000000000000000000000000000000000000000000606082015260800190565b60405181810167ffffffffffffffff81118282101715612dd557612dd56130c3565b604052919050565b600067ffffffffffffffff821115612df757612df76130c3565b50601f01601f191660200190565b60008219821115612e1857612e18613097565b500190565b600082612e2c57612e2c6130ad565b500490565b600060ff831680612e4457612e446130ad565b8060ff84160491505092915050565b80825b6001808611612e655750612e90565b818704821115612e7757612e77613097565b80861615612e8457918102915b9490941c938002612e56565b94509492505050565b60006102887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484600082612ed057506001610288565b81612edd57506000610288565b8160018114612ef35760028114612efd57612f2a565b6001915050610288565b60ff841115612f0e57612f0e613097565b6001841b915084821115612f2457612f24613097565b50610288565b5060208310610133831016604e8410600b8410161715612f5d575081810a83811115612f5857612f58613097565b610288565b612f6a8484846001612e53565b808604821115612f7c57612f7c613097565b02949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612fbd57612fbd613097565b500290565b600082821015612fd457612fd4613097565b500390565b600060ff821660ff841680821015612ff357612ff3613097565b90039392505050565b60005b83811015613017578181015183820152602001612fff565b83811115610a305750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561305a5761305a613097565b5060010190565b600082613070576130706130ad565b500690565b600060ff831680613088576130886130ad565b8060ff84160691505092915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146130fb57600080fd5b5056fea2646970667358221220607c4bf60f62fb1d05276fce640c1e0d46510eeefc3dfe37164a02c39de3f85f64736f6c63430008000033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000086e4dc95c7fbdbf52e33d563bbdb00823894c287000000000000000000000000fe5e5d361b2ad62c541bab87c45a0b9b018389a2000000000000000000000000ad87e3b217c66b0d45deafbc540330d300811b94000000000000000000000000a0c68c638235ee32657e8f720a23cec1bfc77c77
-----Decoded View---------------
Arg [0] : _checkpointManager (address): 0x86E4Dc95c7FBdBf52e33D563BbDB00823894C287
Arg [1] : _fxRoot (address): 0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2
Arg [2] : _fxERC20Token (address): 0xAd87e3b217c66B0D45dEaFBC540330d300811b94
Arg [3] : _rootChainManager (address): 0xA0c68C638235ee32657e8f720a23ceC1bFc77C77
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000086e4dc95c7fbdbf52e33d563bbdb00823894c287
Arg [1] : 000000000000000000000000fe5e5d361b2ad62c541bab87c45a0b9b018389a2
Arg [2] : 000000000000000000000000ad87e3b217c66b0d45deafbc540330d300811b94
Arg [3] : 000000000000000000000000a0c68c638235ee32657e8f720a23cec1bfc77c77
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 23.58% | $0.001411 | 999,844,314.6742 | $1,410,750.33 | |
ETH | 22.99% | $0.000183 | 7,519,852,427.9076 | $1,375,381.01 | |
ETH | 14.61% | $0.087381 | 10,000,000 | $873,805.01 | |
ETH | 9.17% | $0.036284 | 15,122,148.1717 | $548,692.86 | |
ETH | 8.49% | $0.028919 | 17,570,172.5906 | $508,103.39 | |
ETH | 6.10% | $0.048687 | 7,496,807.2285 | $364,999.15 | |
ETH | 2.95% | $0.015089 | 11,680,074.9061 | $176,240.88 | |
ETH | 2.88% | $0.000726 | 237,169,527.4814 | $172,236.21 | |
ETH | 2.14% | $0.00076 | 168,390,041.1245 | $128,043.79 | |
ETH | 2.05% | $2,572.09 | 47.6065 | $122,448.14 | |
ETH | 1.12% | $0.004211 | 15,917,112.0723 | $67,027.98 | |
ETH | 0.80% | $0.003634 | 13,091,582.6639 | $47,579.39 | |
ETH | 0.60% | $0.00016 | 223,297,003.4359 | $35,649.37 | |
ETH | 0.58% | $0.007465 | 4,655,349.0362 | $34,752.11 | |
ETH | 0.47% | $0.00291 | 9,711,002.455 | $28,258.29 | |
ETH | 0.35% | $0.00261 | 7,930,134.0661 | $20,699.42 | |
ETH | 0.23% | $0.003985 | 3,500,001 | $13,947.04 | |
ETH | 0.21% | $0.997111 | 12,852.1979 | $12,815.06 | |
ETH | 0.21% | $0.004118 | 3,002,800 | $12,364.42 | |
ETH | 0.13% | $0.026831 | 296,738.0774 | $7,961.82 | |
ETH | 0.10% | $0.017185 | 363,914.4424 | $6,253.92 | |
ETH | 0.09% | $0.022718 | 236,848.7803 | $5,380.79 | |
ETH | 0.05% | <$0.000001 | 12,174,954,354.0787 | $3,141.99 | |
ETH | 0.04% | $0.000025 | 91,271,820 | $2,239.45 | |
ETH | 0.02% | $0.000975 | 966,159.0062 | $941.79 | |
ETH | 0.01% | $0.009805 | 81,000 | $794.24 | |
ETH | <0.01% | <$0.000001 | 2,075,000,000 | $460.2 | |
ETH | <0.01% | $0.060181 | 6,850.9616 | $412.3 | |
ETH | <0.01% | $0.004435 | 66,900.9904 | $296.72 | |
ETH | <0.01% | $0.000137 | 1,737,200 | $237.42 | |
ETH | <0.01% | $0.379089 | 552.9356 | $209.61 | |
ETH | <0.01% | $9.84 | 16.8241 | $165.55 | |
ETH | <0.01% | $0.999872 | 98.0261 | $98.01 | |
ETH | <0.01% | $0.000009 | 10,417,291.7576 | $93.44 | |
ETH | <0.01% | $0.113991 | 777 | $88.57 | |
ETH | <0.01% | $1.1 | 50.2038 | $55.44 | |
ETH | <0.01% | $0.000058 | 822,542.612 | $48.1 | |
ETH | <0.01% | $0.00536 | 6,969 | $37.35 | |
ETH | <0.01% | $0.310736 | 100 | $31.07 | |
ETH | <0.01% | $0.011271 | 2,000 | $22.54 | |
ETH | <0.01% | $0.00237 | 3,000 | $7.11 | |
ETH | <0.01% | $0.362008 | 10 | $3.62 | |
ETH | <0.01% | <$0.000001 | 38,342,714.3496 | $3.48 | |
ETH | <0.01% | $517.34 | 0.0048278 | $2.5 |
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.
Address QR Code
My Address - Private Name Tag or Note
My Name Tag:
Private Note:
Please DO NOT store any passwords or private keys here.
The compiled contract might be susceptible to FullInlinerNonExpressionSplitArgumentEvaluationOrder (low-severity), MissingSideEffectsOnSelectorAccess (low-severity), AbiReencodingHeadOverflowWithStaticArrayCleanup (medium-severity), DirtyBytesArrayToStorage (low-severity), DataLocationChangeInInternalOverride (very low-severity), NestedCalldataArrayAbiReencodingSizeValidation (very low-severity), SignedImmutables (very low-severity), ABIDecodeTwoDimensionalArrayMemory (very low-severity), KeccakCaching (medium-severity) Solidity Compiler Bugs.
Connect a Wallet
Connect a Wallet
Connect a Wallet
Address Cards
Before You Copy
This website uses cookies to improve your experience. By continuing to use this website, you agree to its Terms and Privacy Policy.