Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 15815857 | 764 days ago | IN | 0 ETH | 0.02439616 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
L1GatewayRouter
Compiler Version
v0.6.11+commit.5ef660b1
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; import "arb-bridge-eth/contracts/libraries/Whitelist.sol"; import { ArbitrumEnabledToken } from "../ICustomToken.sol"; import "../L1ArbitrumMessenger.sol"; import "../../libraries/gateway/GatewayRouter.sol"; import "../../arbitrum/gateway/L2GatewayRouter.sol"; import "../../libraries/ERC165.sol"; import "./IL1GatewayRouter.sol"; import "./IL1ArbitrumGateway.sol"; /** * @title Handles deposits from Erhereum into Arbitrum. Tokens are routered to their appropriate L1 gateway (Router itself also conforms to the Gateway itnerface). * @notice Router also serves as an L1-L2 token address oracle. */ contract L1GatewayRouter is WhitelistConsumer, L1ArbitrumMessenger, GatewayRouter, ERC165, IL1GatewayRouter { address public override owner; address public override inbox; modifier onlyOwner() { require(msg.sender == owner, "ONLY_OWNER"); _; } function initialize( address _owner, address _defaultGateway, address, // was _whitelist, now unused address _counterpartGateway, address _inbox ) public { GatewayRouter._initialize(_counterpartGateway, address(0), _defaultGateway); owner = _owner; WhitelistConsumer.whitelist = address(0); inbox = _inbox; } function setDefaultGateway( address newL1DefaultGateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost ) external payable onlyOwner returns (uint256) { defaultGateway = newL1DefaultGateway; emit DefaultGatewayUpdated(newL1DefaultGateway); address l2NewDefaultGateway; if (newL1DefaultGateway != address(0)) { l2NewDefaultGateway = TokenGateway(newL1DefaultGateway).counterpartGateway(); } bytes memory data = abi.encodeWithSelector( L2GatewayRouter.setDefaultGateway.selector, l2NewDefaultGateway ); return sendTxToL2( inbox, counterpartGateway, msg.sender, msg.value, 0, L2GasParams({ _maxSubmissionCost: _maxSubmissionCost, _maxGas: _maxGas, _gasPriceBid: _gasPriceBid }), data ); } function setOwner(address newOwner) external onlyOwner { require(newOwner != address(0), "INVALID_OWNER"); // set newOwner to address(1) to disable owner and keep `initialize` safe owner = newOwner; } function _setGateways( address[] memory _token, address[] memory _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, address _creditBackAddress ) internal returns (uint256) { require(_token.length == _gateway.length, "WRONG_LENGTH"); for (uint256 i = 0; i < _token.length; i++) { l1TokenToGateway[_token[i]] = _gateway[i]; emit GatewaySet(_token[i], _gateway[i]); // overwrite memory so the L2 router receives the L2 address of each gateway if (_gateway[i] != address(0) && _gateway[i] != DISABLED) { // if we are assigning a gateway to the token, the address oracle of the gateway // must return something other than the 0 address // this check helps avoid misconfiguring gateways require( TokenGateway(_gateway[i]).calculateL2TokenAddress(_token[i]) != address(0), "TOKEN_NOT_HANDLED_BY_GATEWAY" ); _gateway[i] = TokenGateway(_gateway[i]).counterpartGateway(); } } bytes memory data = abi.encodeWithSelector( L2GatewayRouter.setGateway.selector, _token, _gateway ); return sendTxToL2( inbox, counterpartGateway, _creditBackAddress, msg.value, 0, L2GasParams({ _maxSubmissionCost: _maxSubmissionCost, _maxGas: _maxGas, _gasPriceBid: _gasPriceBid }), data ); } /** * @notice Allows L1 Token contract to trustlessly register its gateway. (other setGateway method allows excess eth recovery from _maxSubmissionCost and is recommended) * @param _gateway l1 gateway address * @param _maxGas max gas for L2 retryable exrecution * @param _gasPriceBid gas price for L2 retryable ticket * @param _maxSubmissionCost base submission cost L2 retryable tick3et * @return Retryable ticket ID */ function setGateway( address _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost ) external payable override returns (uint256) { return setGateway(_gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender); } /** * @notice Allows L1 Token contract to trustlessly register its gateway. * @param _gateway l1 gateway address * @param _maxGas max gas for L2 retryable exrecution * @param _gasPriceBid gas price for L2 retryable ticket * @param _maxSubmissionCost base submission cost L2 retryable tick3et * @param _creditBackAddress address for crediting back overpayment of _maxSubmissionCost * @return Retryable ticket ID */ function setGateway( address _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, address _creditBackAddress ) public payable override returns (uint256) { require( ArbitrumEnabledToken(msg.sender).isArbitrumEnabled() == uint8(0xa4b1), "NOT_ARB_ENABLED" ); require(_gateway.isContract(), "NOT_TO_CONTRACT"); address currGateway = getGateway(msg.sender); if (currGateway != address(0) && currGateway != defaultGateway) { // if gateway is already set to a non-default gateway, don't allow it to set a different gateway require(currGateway == _gateway, "NO_UPDATE_TO_DIFFERENT_ADDR"); } address[] memory _tokenArr = new address[](1); _tokenArr[0] = address(msg.sender); address[] memory _gatewayArr = new address[](1); _gatewayArr[0] = _gateway; return _setGateways( _tokenArr, _gatewayArr, _maxGas, _gasPriceBid, _maxSubmissionCost, _creditBackAddress ); } function setGateways( address[] memory _token, address[] memory _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost ) external payable onlyOwner returns (uint256) { // it is assumed that token and gateway are both contracts // require(_token[i].isContract() && _gateway[i].isContract(), "NOT_CONTRACT"); return _setGateways(_token, _gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender); } function outboundTransfer( address _token, address _to, uint256 _amount, uint256 _maxGas, uint256 _gasPriceBid, bytes calldata _data ) public payable override(GatewayRouter, ITokenGateway) returns (bytes memory) { return super.outboundTransfer(_token, _to, _amount, _maxGas, _gasPriceBid, _data); } /** * @notice Deposit ERC20 token from Ethereum into Arbitrum using the registered or otherwise default gateway * @dev Some legacy gateway might not have the outboundTransferCustomRefund method and will revert, in such case use outboundTransfer instead * L2 address alias will not be applied to the following types of addresses on L1: * - 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 * @param _token L1 address of ERC20 * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract), not subject to L2 aliasing This account, or its L2 alias if it have code in L1, will also be able to cancel the retryable ticket and receive callvalue refund * @param _amount Token Amount * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution * @param _gasPriceBid Gas price for L2 execution * @param _data encoded data from router and user * @return res abi encoded inbox sequence number */ function outboundTransferCustomRefund( address _token, address _refundTo, address _to, uint256 _amount, uint256 _maxGas, uint256 _gasPriceBid, bytes calldata _data ) public payable override returns (bytes memory) { address gateway = getGateway(_token); bytes memory gatewayData = GatewayMessageHandler.encodeFromRouterToGateway( msg.sender, _data ); emit TransferRouted(_token, msg.sender, _to, gateway); // here we use `IL1ArbitrumGateway` since we don't assume all ITokenGateway implements `outboundTransferCustomRefund` return IL1ArbitrumGateway(gateway).outboundTransferCustomRefund{ value: msg.value }( _token, _refundTo, _to, _amount, _maxGas, _gasPriceBid, gatewayData ); } modifier onlyCounterpartGateway() override { // don't expect messages from L2 router revert("ONLY_COUNTERPART_GATEWAY"); _; } function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) returns (bool) { // registering interfaces that is added after arb-bridge-peripherals >1.0.11 // using function selector instead of single function interfaces to reduce bloat return interfaceId == this.outboundTransferCustomRefund.selector || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; abstract contract WhitelistConsumer { address public whitelist; event WhitelistSourceUpdated(address newSource); modifier onlyWhitelisted() { if (whitelist != address(0)) { require(Whitelist(whitelist).isAllowed(msg.sender), "NOT_WHITELISTED"); } _; } function updateWhitelistSource(address newSource) external { require(msg.sender == whitelist, "NOT_FROM_LIST"); whitelist = newSource; emit WhitelistSourceUpdated(newSource); } } contract Whitelist { address public owner; mapping(address => bool) public isAllowed; event OwnerUpdated(address newOwner); event WhitelistUpgraded(address newWhitelist, address[] targets); constructor() public { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "ONLY_OWNER"); _; } function setOwner(address newOwner) external onlyOwner { owner = newOwner; emit OwnerUpdated(newOwner); } function setWhitelist(address[] memory user, bool[] memory val) external onlyOwner { require(user.length == val.length, "INVALID_INPUT"); for (uint256 i = 0; i < user.length; i++) { isAllowed[user[i]] = val[i]; } } // set new whitelist to address(0) to disable whitelist function triggerConsumers(address newWhitelist, address[] memory targets) external onlyOwner { for (uint256 i = 0; i < targets.length; i++) { WhitelistConsumer(targets[i]).updateWhitelistSource(newWhitelist); } emit WhitelistUpgraded(newWhitelist, targets); } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; interface ArbitrumEnabledToken { /// @notice should return `0xa4b1` if token is enabled for arbitrum gateways function isArbitrumEnabled() external view returns (uint8); } /** * @title Minimum expected interface for L1 custom token (see TestCustomTokenL1.sol for an example implementation) */ interface ICustomToken is ArbitrumEnabledToken { /** * @notice Should make an external call to EthERC20Bridge.registerCustomL2Token */ function registerTokenOnL2( address l2CustomTokenAddress, uint256 maxSubmissionCostForCustomBridge, uint256 maxSubmissionCostForRouter, uint256 maxGasForCustomBridge, uint256 maxGasForRouter, uint256 gasPriceBid, uint256 valueForGateway, uint256 valueForRouter, address creditBackAddress ) external payable; function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); function balanceOf(address account) external view returns (uint256); } interface L1MintableToken is ICustomToken { function bridgeMint(address account, uint256 amount) external; }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; import "arb-bridge-eth/contracts/bridge/interfaces/IInbox.sol"; import "arb-bridge-eth/contracts/bridge/interfaces/IOutbox.sol"; /// @notice L1 utility contract to assist with L1 <=> L2 interactions /// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing abstract contract L1ArbitrumMessenger { event TxToL2(address indexed _from, address indexed _to, uint256 indexed _seqNum, bytes _data); struct L2GasParams { uint256 _maxSubmissionCost; uint256 _maxGas; uint256 _gasPriceBid; } function sendTxToL2CustomRefund( address _inbox, address _to, address _refundTo, address _user, uint256 _l1CallValue, uint256 _l2CallValue, L2GasParams memory _l2GasParams, bytes memory _data ) internal returns (uint256) { // alternative function entry point when struggling with the stack size return sendTxToL2CustomRefund( _inbox, _to, _refundTo, _user, _l1CallValue, _l2CallValue, _l2GasParams._maxSubmissionCost, _l2GasParams._maxGas, _l2GasParams._gasPriceBid, _data ); } function sendTxToL2( address _inbox, address _to, address _user, uint256 _l1CallValue, uint256 _l2CallValue, L2GasParams memory _l2GasParams, bytes memory _data ) internal returns (uint256) { // alternative function entry point when struggling with the stack size return sendTxToL2( _inbox, _to, _user, _l1CallValue, _l2CallValue, _l2GasParams._maxSubmissionCost, _l2GasParams._maxGas, _l2GasParams._gasPriceBid, _data ); } function sendTxToL2CustomRefund( address _inbox, address _to, address _refundTo, address _user, uint256 _l1CallValue, uint256 _l2CallValue, uint256 _maxSubmissionCost, uint256 _maxGas, uint256 _gasPriceBid, bytes memory _data ) internal returns (uint256) { uint256 seqNum = IInbox(_inbox).createRetryableTicket{ value: _l1CallValue }( _to, _l2CallValue, _maxSubmissionCost, _refundTo, // only refund excess fee to the custom address _user, // user can cancel the retryable and receive call value refund _maxGas, _gasPriceBid, _data ); emit TxToL2(_user, _to, seqNum, _data); return seqNum; } function sendTxToL2( address _inbox, address _to, address _user, uint256 _l1CallValue, uint256 _l2CallValue, uint256 _maxSubmissionCost, uint256 _maxGas, uint256 _gasPriceBid, bytes memory _data ) internal returns (uint256) { return sendTxToL2CustomRefund( _inbox, _to, _user, _user, _l1CallValue, _l2CallValue, _maxSubmissionCost, _maxGas, _gasPriceBid, _data ); } function getBridge(address _inbox) internal view returns (IBridge) { return IInbox(_inbox).bridge(); } /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies function getL2ToL1Sender(address _inbox) internal view returns (address) { IOutbox outbox = IOutbox(getBridge(_inbox).activeOutbox()); address l2ToL1Sender = outbox.l2ToL1Sender(); require(l2ToL1Sender != address(0), "NO_SENDER"); return l2ToL1Sender; } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; import "arb-bridge-eth/contracts/libraries/ProxyUtil.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "./TokenGateway.sol"; import "./GatewayMessageHandler.sol"; import "./IGatewayRouter.sol"; /** * @title Common interface for L1 and L2 Gateway Routers */ abstract contract GatewayRouter is TokenGateway, IGatewayRouter { using Address for address; address internal constant ZERO_ADDR = address(0); address internal constant DISABLED = address(1); mapping(address => address) public l1TokenToGateway; address public override defaultGateway; event TransferRouted( address indexed token, address indexed _userFrom, address indexed _userTo, address gateway ); event GatewaySet(address indexed l1Token, address indexed gateway); event DefaultGatewayUpdated(address newDefaultGateway); function postUpgradeInit() external { // it is assumed the L2 Arbitrum Gateway contract is behind a Proxy controlled by a proxy admin // this function can only be called by the proxy admin contract address proxyAdmin = ProxyUtil.getProxyAdmin(); require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN"); // this has no other logic since the current upgrade doesn't require this logic } function _initialize( address _counterpartGateway, address _router, address _defaultGateway ) internal { // if you are a router, you can't have a router require(_router == address(0), "BAD_ROUTER"); TokenGateway._initialize(_counterpartGateway, _router); // default gateway can have 0 address defaultGateway = _defaultGateway; } function finalizeInboundTransfer( address, /* _token */ address, /* _from */ address, /* _to */ uint256, /* _amount */ bytes calldata /* _data */ ) external payable virtual override { revert("ONLY_OUTBOUND_ROUTER"); } function outboundTransfer( address _token, address _to, uint256 _amount, uint256 _maxGas, uint256 _gasPriceBid, bytes calldata _data ) public payable virtual override returns (bytes memory) { // this function is kept instead of delegating to outboundTransferCustomRefund to allow // compatibility with older gateways that did not implement outboundTransferCustomRefund address gateway = getGateway(_token); bytes memory gatewayData = GatewayMessageHandler.encodeFromRouterToGateway( msg.sender, _data ); emit TransferRouted(_token, msg.sender, _to, gateway); return ITokenGateway(gateway).outboundTransfer{ value: msg.value }( _token, _to, _amount, _maxGas, _gasPriceBid, gatewayData ); } function getOutboundCalldata( address _token, address _from, address _to, uint256 _amount, bytes memory _data ) public view virtual override returns (bytes memory) { address gateway = getGateway(_token); return TokenGateway(gateway).getOutboundCalldata(_token, _from, _to, _amount, _data); } function getGateway(address _token) public view virtual override returns (address gateway) { gateway = l1TokenToGateway[_token]; if (gateway == ZERO_ADDR) { // if no gateway value set, use default gateway gateway = defaultGateway; } if (gateway == DISABLED || !gateway.isContract()) { // not a valid gateway return ZERO_ADDR; } return gateway; } function calculateL2TokenAddress(address l1ERC20) public view virtual override(TokenGateway, ITokenGateway) returns (address) { address gateway = getGateway(l1ERC20); if (gateway == ZERO_ADDR) { return ZERO_ADDR; } return TokenGateway(gateway).calculateL2TokenAddress(l1ERC20); } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; import "../../libraries/gateway/GatewayRouter.sol"; import "../../ethereum/gateway/L1GatewayRouter.sol"; import "../L2ArbitrumMessenger.sol"; import "arb-bridge-eth/contracts/libraries/AddressAliasHelper.sol"; /** * @title Handles withdrawals from Ethereum into Arbitrum. Tokens are routered to their appropriate L2 gateway (Router itself also conforms to the Gateway interface). * @notice Router also serves as an L2-L1 token address oracle. */ contract L2GatewayRouter is GatewayRouter, L2ArbitrumMessenger { modifier onlyCounterpartGateway() override { require( msg.sender == AddressAliasHelper.applyL1ToL2Alias(counterpartGateway), "ONLY_COUNTERPART_GATEWAY" ); _; } function initialize(address _counterpartGateway, address _defaultGateway) public { GatewayRouter._initialize(_counterpartGateway, address(0), _defaultGateway); } function setGateway(address[] memory _l1Token, address[] memory _gateway) external onlyCounterpartGateway { // counterpart gateway (L1 router) should never allow wrong lengths assert(_l1Token.length == _gateway.length); for (uint256 i = 0; i < _l1Token.length; i++) { l1TokenToGateway[_l1Token[i]] = _gateway[i]; emit GatewaySet(_l1Token[i], _gateway[i]); } } function outboundTransfer( address _l1Token, address _to, uint256 _amount, bytes calldata _data ) public payable returns (bytes memory) { return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data); } function setDefaultGateway(address newL2DefaultGateway) external onlyCounterpartGateway { defaultGateway = newL2DefaultGateway; emit DefaultGatewayUpdated(newL2DefaultGateway); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) // With pragma modification to support ^0.6.11 // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.6/contracts/utils/introspection/ERC165.sol pragma solidity ^0.6.11; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; import "../../libraries/gateway/ITokenGateway.sol"; import "../../libraries/IERC165.sol"; /** * @title Handles deposits from Erhereum into Arbitrum. Tokens are routered to their appropriate L1 gateway (Router itself also conforms to the Gateway itnerface). * @notice Router also serves as an L1-L2 token address oracle. */ interface IL1GatewayRouter is ITokenGateway, IERC165 { /** * @notice Deposit ERC20 token from Ethereum into Arbitrum using the registered or otherwise default gateway * @dev Some legacy gateway might not have the outboundTransferCustomRefund method and will revert, in such case use outboundTransfer instead * L2 address alias will not be applied to the following types of addresses on L1: * - 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 * @param _token L1 address of ERC20 * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract), not subject to L2 aliasing This account, or its L2 alias if it have code in L1, will also be able to cancel the retryable ticket and receive callvalue refund * @param _amount Token Amount * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution * @param _gasPriceBid Gas price for L2 execution * @param _data encoded data from router and user * @return res abi encoded inbox sequence number */ function outboundTransferCustomRefund( address _token, address _refundTo, address _to, uint256 _amount, uint256 _maxGas, uint256 _gasPriceBid, bytes calldata _data ) external payable returns (bytes memory); /** * @notice Allows L1 Token contract to trustlessly register its gateway. * @param _gateway l1 gateway address * @param _maxGas max gas for L2 retryable exrecution * @param _gasPriceBid gas price for L2 retryable ticket * @param _maxSubmissionCost base submission cost L2 retryable tick3et * @param _creditBackAddress address for crediting back overpayment of _maxSubmissionCost * @return Retryable ticket ID */ function setGateway( address _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, address _creditBackAddress ) external payable returns (uint256); /** * @notice Allows L1 Token contract to trustlessly register its gateway. (other setGateway method allows excess eth recovery from _maxSubmissionCost and is recommended) * @param _gateway l1 gateway address * @param _maxGas max gas for L2 retryable exrecution * @param _gasPriceBid gas price for L2 retryable ticket * @param _maxSubmissionCost base submission cost L2 retryable tick3et * @return Retryable ticket ID */ function setGateway( address _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost ) external payable returns (uint256); function owner() external view returns (address); function inbox() external view returns (address); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; import "../../libraries/gateway/ITokenGateway.sol"; import "../../libraries/IERC165.sol"; /** * @title Common interface for gatways on L1 messaging to Arbitrum. */ interface IL1ArbitrumGateway is ITokenGateway, IERC165 { function inbox() external view returns (address); /** * @notice Deposit ERC20 token from Ethereum into Arbitrum. If L2 side hasn't been deployed yet, includes name/symbol/decimals data for initial L2 deploy. Initiate by GatewayRouter. * @dev L2 address alias will not be applied to the following types of addresses on L1: * - 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 * @param _l1Token L1 address of ERC20 * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract), not subject to L2 aliasing This account, or its L2 alias if it have code in L1, will also be able to cancel the retryable ticket and receive callvalue refund * @param _amount Token Amount * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution * @param _gasPriceBid Gas price for L2 execution * @param _data encoded data from router and user * @return res abi encoded inbox sequence number */ // * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee function outboundTransferCustomRefund( address _l1Token, address _refundTo, address _to, uint256 _amount, uint256 _maxGas, uint256 _gasPriceBid, bytes calldata _data ) external payable returns (bytes memory); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; import "./IBridge.sol"; import "./IMessageProvider.sol"; interface IInbox is IMessageProvider { function sendL2Message(bytes calldata messageData) external returns (uint256); function sendUnsignedTransaction( uint256 maxGas, uint256 gasPriceBid, uint256 nonce, address destAddr, uint256 amount, bytes calldata data ) external returns (uint256); function sendContractTransaction( uint256 maxGas, uint256 gasPriceBid, address destAddr, uint256 amount, bytes calldata data ) external returns (uint256); function sendL1FundedUnsignedTransaction( uint256 maxGas, uint256 gasPriceBid, uint256 nonce, address destAddr, bytes calldata data ) external payable returns (uint256); function sendL1FundedContractTransaction( uint256 maxGas, uint256 gasPriceBid, address destAddr, bytes calldata data ) external payable returns (uint256); function createRetryableTicket( address destAddr, uint256 arbTxCallValue, uint256 maxSubmissionCost, address submissionRefundAddress, address valueRefundAddress, uint256 maxGas, uint256 gasPriceBid, bytes calldata data ) external payable returns (uint256); function unsafeCreateRetryableTicket( address destAddr, uint256 arbTxCallValue, uint256 maxSubmissionCost, address submissionRefundAddress, address valueRefundAddress, uint256 maxGas, uint256 gasPriceBid, bytes calldata data ) external payable returns (uint256); function depositEth(uint256 maxSubmissionCost) external payable returns (uint256); function bridge() external view returns (IBridge); function pauseCreateRetryables() external; function unpauseCreateRetryables() external; function startRewriteAddress() external; function stopRewriteAddress() external; }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; interface IOutbox { event OutboxEntryCreated( uint256 indexed batchNum, uint256 outboxEntryIndex, bytes32 outputRoot, uint256 numInBatch ); event OutBoxTransactionExecuted( address indexed destAddr, address indexed l2Sender, uint256 indexed outboxEntryIndex, uint256 transactionIndex ); function l2ToL1Sender() external view returns (address); function l2ToL1Block() external view returns (uint256); function l2ToL1EthBlock() external view returns (uint256); function l2ToL1Timestamp() external view returns (uint256); function l2ToL1BatchNum() external view returns (uint256); function l2ToL1OutputId() external view returns (bytes32); function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) external; function outboxEntryExists(uint256 batchNum) external view returns (bool); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; interface IBridge { event MessageDelivered( uint256 indexed messageIndex, bytes32 indexed beforeInboxAcc, address inbox, uint8 kind, address sender, bytes32 messageDataHash ); event BridgeCallTriggered( address indexed outbox, address indexed destAddr, uint256 amount, bytes data ); event InboxToggle(address indexed inbox, bool enabled); event OutboxToggle(address indexed outbox, bool enabled); function deliverMessageToInbox( uint8 kind, address sender, bytes32 messageDataHash ) external payable returns (uint256); function executeCall( address destAddr, uint256 amount, bytes calldata data ) external returns (bool success, bytes memory returnData); // These are only callable by the admin function setInbox(address inbox, bool enabled) external; function setOutbox(address inbox, bool enabled) external; // View functions function activeOutbox() external view returns (address); function allowedInboxes(address inbox) external view returns (bool); function allowedOutboxes(address outbox) external view returns (bool); function inboxAccs(uint256 index) external view returns (bytes32); function messageCount() external view returns (uint256); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; interface IMessageProvider { event InboxMessageDelivered(uint256 indexed messageNum, bytes data); event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; library ProxyUtil { function getProxyAdmin() internal view returns (address admin) { // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/proxy/TransparentUpgradeableProxy.sol#L48 // Storage slot with the admin of the proxy contract. // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; assembly { admin := sload(slot) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <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; // solhint-disable-next-line no-inline-assembly 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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; import "./ITokenGateway.sol"; import "@openzeppelin/contracts/utils/Address.sol"; abstract contract TokenGateway is ITokenGateway { using Address for address; address public counterpartGateway; address public router; // This modifier is overriden in gateways to validate the message sender // For L1 to L2 messages need to be validated against the aliased counterpartGateway // For L2 to L1 messages need to be validated against the bridge and L2ToL1Sender // prettier-ignore modifier onlyCounterpartGateway() virtual; function _initialize(address _counterpartGateway, address _router) internal virtual { // This initializes internal variables of the abstract contract it can be chained together with other functions. // It is virtual so subclasses can override or wrap around this logic. // An example where this is useful is different subclasses that validate the router address differently require(_counterpartGateway != address(0), "INVALID_COUNTERPART"); require(counterpartGateway == address(0), "ALREADY_INIT"); counterpartGateway = _counterpartGateway; router = _router; } function isRouter(address _target) internal view returns (bool isTargetRouter) { return _target == router; } /** * @notice Calculate the address used when bridging an ERC20 token * @dev the L1 and L2 address oracles may not always be in sync. * For example, a custom token may have been registered but not deploy or the contract self destructed. * @param l1ERC20 address of L1 token * @return L2 address of a bridged ERC20 token */ function calculateL2TokenAddress(address l1ERC20) public view virtual override returns (address); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; /// @notice this library manages encoding and decoding of gateway communication library GatewayMessageHandler { // these are for communication from L1 to L2 gateway function encodeToL2GatewayMsg(bytes memory gatewayData, bytes memory callHookData) internal pure returns (bytes memory res) { res = abi.encode(gatewayData, callHookData); } function parseFromL1GatewayMsg(bytes calldata _data) internal pure returns (bytes memory gatewayData, bytes memory callHookData) { // abi decode may revert, but the encoding is done by L1 gateway, so we trust it (gatewayData, callHookData) = abi.decode(_data, (bytes, bytes)); } // these are for communication from L2 to L1 gateway function encodeFromL2GatewayMsg(uint256 exitNum, bytes memory callHookData) internal pure returns (bytes memory res) { res = abi.encode(exitNum, callHookData); } function parseToL1GatewayMsg(bytes calldata _data) internal pure returns (uint256 exitNum, bytes memory callHookData) { // abi decode may revert, but the encoding is done by L1 gateway, so we trust it (exitNum, callHookData) = abi.decode(_data, (uint256, bytes)); } // these are for communication from router to gateway function encodeFromRouterToGateway(address _from, bytes calldata _data) internal pure returns (bytes memory res) { // abi decode may revert, but the encoding is done by L1 gateway, so we trust it return abi.encode(_from, _data); } function parseFromRouterToGateway(bytes calldata _data) internal pure returns (address, bytes memory res) { // abi decode may revert, but the encoding is done by L1 gateway, so we trust it return abi.decode(_data, (address, bytes)); } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; import "arb-bridge-eth/contracts/libraries/ProxyUtil.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "./TokenGateway.sol"; import "./GatewayMessageHandler.sol"; /** * @title Common interface for L1 and L2 Gateway Routers */ interface IGatewayRouter is ITokenGateway { function defaultGateway() external view returns (address gateway); event TransferRouted( address indexed token, address indexed _userFrom, address indexed _userTo, address gateway ); event GatewaySet(address indexed l1Token, address indexed gateway); event DefaultGatewayUpdated(address newDefaultGateway); function getGateway(address _token) external view returns (address gateway); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; interface ITokenGateway { /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated // event OutboundTransferInitiated( // address token, // address indexed _from, // address indexed _to, // uint256 indexed _transferId, // uint256 _amount, // bytes _data // ); /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized // event InboundTransferFinalized( // address token, // address indexed _from, // address indexed _to, // uint256 indexed _transferId, // uint256 _amount, // bytes _data // ); function outboundTransfer( address _token, address _to, uint256 _amount, uint256 _maxGas, uint256 _gasPriceBid, bytes calldata _data ) external payable returns (bytes memory); function finalizeInboundTransfer( address _token, address _from, address _to, uint256 _amount, bytes calldata _data ) external payable; /** * @notice Calculate the address used when bridging an ERC20 token * @dev the L1 and L2 address oracles may not always be in sync. * For example, a custom token may have been registered but not deploy or the contract self destructed. * @param l1ERC20 address of L1 token * @return L2 address of a bridged ERC20 token */ function calculateL2TokenAddress(address l1ERC20) external view returns (address); function getOutboundCalldata( address _token, address _from, address _to, uint256 _amount, bytes memory _data ) external view returns (bytes memory); }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2020, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; import "arbos-precompiles/arbos/builtin/ArbSys.sol"; /// @notice L2 utility contract to assist with L1 <=> L2 interactions /// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing abstract contract L2ArbitrumMessenger { address internal constant ARB_SYS_ADDRESS = address(100); event TxToL1(address indexed _from, address indexed _to, uint256 indexed _id, bytes _data); function sendTxToL1( uint256 _l1CallValue, address _from, address _to, bytes memory _data ) internal returns (uint256) { uint256 _id = ArbSys(ARB_SYS_ADDRESS).sendTxToL1{ value: _l1CallValue }(_to, _data); emit TxToL1(_from, _to, _id, _data); return _id; } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2019-2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.6.11; library AddressAliasHelper { uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); /// @notice Utility function that converts the address in the L1 that submitted a tx to /// the inbox to the msg.sender viewed in the L2 /// @param l1Address the address in the L1 that triggered the tx to L2 /// @return l2Address L2 address as viewed in msg.sender function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { l2Address = address(uint160(l1Address) + offset); } /// @notice Utility function that converts the msg.sender viewed in the L2 to the /// address in the L1 that submitted a tx to the inbox /// @param l2Address L2 address as viewed in msg.sender /// @return l1Address the address in the L1 that triggered the tx to L2 function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { l1Address = address(uint160(l2Address) - offset); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) // With pragma modification to allow interface compatibility with >=0.6.9 <0.9.0 // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.6/contracts/utils/introspection/IERC165.sol // solhint-disable-next-line compiler-version pragma solidity >=0.6.9 <0.9.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
pragma solidity >=0.4.21 <0.9.0; /** * @title Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. Exposes a variety of system-level functionality. */ interface ArbSys { /** * @notice Get internal version number identifying an ArbOS build * @return version number as int */ function arbOSVersion() external pure returns (uint); function arbChainID() external view returns(uint); /** * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0) * @return block number as int */ function arbBlockNumber() external view returns (uint); /** * @notice Send given amount of Eth to dest from sender. * This is a convenience function, which is equivalent to calling sendTxToL1 with empty calldataForL1. * @param destination recipient address on L1 * @return unique identifier for this L2-to-L1 transaction. */ function withdrawEth(address destination) external payable returns(uint); /** * @notice Send a transaction to L1 * @param destination recipient address on L1 * @param calldataForL1 (optional) calldata for L1 contract call * @return a unique identifier for this L2-to-L1 transaction. */ function sendTxToL1(address destination, bytes calldata calldataForL1) external payable returns(uint); /** * @notice get the number of transactions issued by the given external account or the account sequence number of the given contract * @param account target account * @return the number of transactions issued by the given external account or the account sequence number of the given contract */ function getTransactionCount(address account) external view returns(uint256); /** * @notice get the value of target L2 storage slot * This function is only callable from address 0 to prevent contracts from being able to call it * @param account target account * @param index target index of storage slot * @return stotage value for the given account at the given index */ function getStorageAt(address account, uint256 index) external view returns (uint256); /** * @notice check if current call is coming from l1 * @return true if the caller of this was called directly from L1 */ function isTopLevelCall() external view returns (bool); /** * @notice check if the caller (of this caller of this) is an aliased L1 contract address * @return true iff the caller's address is an alias for an L1 contract address */ function wasMyCallersAddressAliased() external view returns (bool); /** * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing * @return address of the caller's caller, without applying L1 contract address aliasing */ function myCallersAddressWithoutAliasing() external view returns (address); /** * @notice map L1 sender contract address to its L2 alias * @param sender sender address * @param dest destination address * @return aliased sender address */ function mapL1SenderContractAddressToL2Alias(address sender, address dest) external pure returns(address); /** * @notice get the caller's amount of available storage gas * @return amount of storage gas available to the caller */ function getStorageGasAvailable() external view returns(uint); event L2ToL1Transaction(address caller, address indexed destination, uint indexed uniqueId, uint indexed batchNumber, uint indexInBatch, uint arbBlockNum, uint ethBlockNum, uint timestamp, uint callvalue, bytes data); }
{ "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newDefaultGateway","type":"address"}],"name":"DefaultGatewayUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1Token","type":"address"},{"indexed":true,"internalType":"address","name":"gateway","type":"address"}],"name":"GatewaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"_userFrom","type":"address"},{"indexed":true,"internalType":"address","name":"_userTo","type":"address"},{"indexed":false,"internalType":"address","name":"gateway","type":"address"}],"name":"TransferRouted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_seqNum","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_data","type":"bytes"}],"name":"TxToL2","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSource","type":"address"}],"name":"WhitelistSourceUpdated","type":"event"},{"inputs":[{"internalType":"address","name":"l1ERC20","type":"address"}],"name":"calculateL2TokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"counterpartGateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultGateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"finalizeInboundTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getGateway","outputs":[{"internalType":"address","name":"gateway","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"getOutboundCalldata","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_defaultGateway","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"_counterpartGateway","type":"address"},{"internalType":"address","name":"_inbox","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"l1TokenToGateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"outboundTransfer","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_refundTo","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"outboundTransferCustomRefund","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"postUpgradeInit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newL1DefaultGateway","type":"address"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"uint256","name":"_maxSubmissionCost","type":"uint256"}],"name":"setDefaultGateway","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_gateway","type":"address"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"uint256","name":"_maxSubmissionCost","type":"uint256"},{"internalType":"address","name":"_creditBackAddress","type":"address"}],"name":"setGateway","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_gateway","type":"address"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"uint256","name":"_maxSubmissionCost","type":"uint256"}],"name":"setGateway","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_token","type":"address[]"},{"internalType":"address[]","name":"_gateway","type":"address[]"},{"internalType":"uint256","name":"_maxGas","type":"uint256"},{"internalType":"uint256","name":"_gasPriceBid","type":"uint256"},{"internalType":"uint256","name":"_maxSubmissionCost","type":"uint256"}],"name":"setGateways","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newSource","type":"address"}],"name":"updateWhitelistSource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506120d9806100206000396000f3fe6080604052600436106101355760003560e01c80638da5cb5b116100ab578063bda009fe1161006f578063bda009fe14610737578063d2ce7d651461076a578063dd61456914610804578063ed08fdc61461083c578063f887ea401461086f578063fb0e722b1461088457610135565b80638da5cb5b146105ec57806393e59dc11461060157806395fcea7814610616578063a0c76a961461062b578063a7e28d481461070457610135565b80632db09c1c116100fd5780632db09c1c146102915780632e567b36146102a657806347466f981461033c5780634fb1a07b1461036f5780635625a95214610486578063658b53f4146104be57610135565b806301ffc9a71461013a578063032958021461018257806313af4035146101b35780631459457a146101e85780632d67b72d1461023d575b600080fd5b34801561014657600080fd5b5061016e6004803603602081101561015d57600080fd5b50356001600160e01b031916610899565b604080519115158252519081900360200190f35b34801561018e57600080fd5b506101976108c6565b604080516001600160a01b039092168252519081900360200190f35b3480156101bf57600080fd5b506101e6600480360360208110156101d657600080fd5b50356001600160a01b03166108d5565b005b3480156101f457600080fd5b506101e6600480360360a081101561020b57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101358216916080909101351661098e565b61027f600480360360a081101561025357600080fd5b506001600160a01b038135811691602081013591604082013591606081013591608090910135166109d4565b60408051918252519081900360200190f35b34801561029d57600080fd5b50610197610c31565b6101e6600480360360a08110156102bc57600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b8111156102fe57600080fd5b82018360208201111561031057600080fd5b803590602001918460018302840111600160201b8311171561033157600080fd5b509092509050610c40565b34801561034857600080fd5b506101e66004803603602081101561035f57600080fd5b50356001600160a01b0316610c84565b610411600480360360e081101561038557600080fd5b6001600160a01b038235811692602081013582169260408201359092169160608201359160808101359160a0820135919081019060e0810160c0820135600160201b8111156103d357600080fd5b8201836020820111156103e557600080fd5b803590602001918460018302840111600160201b8311171561040657600080fd5b509092509050610d27565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561044b578181015183820152602001610433565b50505050905090810190601f1680156104785780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61027f6004803603608081101561049c57600080fd5b506001600160a01b038135169060208101359060408101359060600135610f97565b61027f600480360360a08110156104d457600080fd5b810190602081018135600160201b8111156104ee57600080fd5b82018360208201111561050057600080fd5b803590602001918460208302840111600160201b8311171561052157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561057057600080fd5b82018360208201111561058257600080fd5b803590602001918460208302840111600160201b831117156105a357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060208101359060400135611134565b3480156105f857600080fd5b5061019761119b565b34801561060d57600080fd5b506101976111aa565b34801561062257600080fd5b506101e66111b9565b34801561063757600080fd5b50610411600480360360a081101561064e57600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b81111561069057600080fd5b8201836020820111156106a257600080fd5b803590602001918460018302840111600160201b831117156106c357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611216945050505050565b34801561071057600080fd5b506101976004803603602081101561072757600080fd5b50356001600160a01b0316611418565b34801561074357600080fd5b506101976004803603602081101561075a57600080fd5b50356001600160a01b03166114c7565b610411600480360360c081101561078057600080fd5b6001600160a01b0382358116926020810135909116916040820135916060810135916080820135919081019060c0810160a0820135600160201b8111156107c657600080fd5b8201836020820111156107d857600080fd5b803590602001918460018302840111600160201b831117156107f957600080fd5b509092509050611529565b61027f6004803603608081101561081a57600080fd5b506001600160a01b038135169060208101359060408101359060600135611546565b34801561084857600080fd5b506101976004803603602081101561085f57600080fd5b50356001600160a01b031661155e565b34801561087b57600080fd5b50610197611579565b34801561089057600080fd5b50610197611588565b60006001600160e01b03198216634fb1a07b60e01b14806108be57506108be82611597565b90505b919050565b6004546001600160a01b031681565b6005546001600160a01b03163314610921576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b6001600160a01b03811661096c576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b61099a826000866115b0565b600580546001600160a01b039687166001600160a01b03199182161790915560008054821690556006805492909616911617909355505050565b600061a4b160ff16336001600160a01b0316638e5f5ad16040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1557600080fd5b505afa158015610a29573d6000803e3d6000fd5b505050506040513d6020811015610a3f57600080fd5b505160ff1614610a88576040805162461bcd60e51b815260206004820152600f60248201526e1393d517d0549097d1539050931151608a1b604482015290519081900360640190fd5b610a9a866001600160a01b0316611627565b610add576040805162461bcd60e51b815260206004820152600f60248201526e1393d517d513d7d0d3d395149050d5608a1b604482015290519081900360640190fd5b6000610ae8336114c7565b90506001600160a01b03811615801590610b1057506004546001600160a01b03828116911614155b15610b7b57866001600160a01b0316816001600160a01b031614610b7b576040805162461bcd60e51b815260206004820152601b60248201527f4e4f5f5550444154455f544f5f444946464552454e545f414444520000000000604482015290519081900360640190fd5b604080516001808252818301909252606091602080830190803683370190505090503381600081518110610bab57fe5b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526060918160200160208202803683370190505090508881600081518110610bf657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050610c2482828a8a8a8a61162d565b9998505050505050505050565b6001546001600160a01b031681565b6040805162461bcd60e51b815260206004820152601460248201527327a7262cafa7aaaa2127aaa7222fa927aaaa22a960611b604482015290519081900360640190fd5b6000546001600160a01b03163314610cd3576040805162461bcd60e51b815260206004820152600d60248201526c1393d517d19493d357d31254d5609a1b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f37389c47920d5cc3229678a0205d0455002c07541a4139ebdce91ac2274657779181900360200190a150565b60606000610d348a6114c7565b90506060610d43338686611a9e565b604080516001600160a01b0385811682529151929350818c169233928f16917f85291dff2161a93c2f12c819d31889c96c63042116f5bc5a205aa701c2c429f5919081900360200190a4816001600160a01b0316634fb1a07b348d8d8d8d8d8d896040518963ffffffff1660e01b815260040180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b0316815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610e4a578181015183820152602001610e32565b50505050905090810190601f168015610e775780820380516001836020036101000a031916815260200191505b50985050505050505050506000604051808303818588803b158015610e9b57600080fd5b505af1158015610eaf573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526020811015610ed957600080fd5b8101908080516040519392919084600160201b821115610ef857600080fd5b908301906020820185811115610f0d57600080fd5b8251600160201b811182820188101715610f2657600080fd5b82525081516020918201929091019080838360005b83811015610f53578181015183820152602001610f3b565b50505050905090810190601f168015610f805780820380516001836020036101000a031916815260200191505b506040525050509250505098975050505050505050565b6005546000906001600160a01b03163314610fe6576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b600480546001600160a01b0387166001600160a01b0319909116811790915560408051918252517f3a8f8eb961383a94d41d193e16a3af73eaddfd5764a4c640257323a1603ac3319181900360200190a160006001600160a01b038616156110b057856001600160a01b0316632db09c1c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561108157600080fd5b505afa158015611095573d6000803e3d6000fd5b505050506040513d60208110156110ab57600080fd5b505190505b604080516001600160a01b038084166024808401919091528351808403909101815260449092018352602082810180516001600160e01b031663f7c9362f60e01b17905260065460015485516060810187528981529283018b905294820189905292936111299383169216903390349060009087611b08565b979650505050505050565b6005546000906001600160a01b03163314611183576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b61119186868686863361162d565b9695505050505050565b6005546001600160a01b031681565b6000546001600160a01b031681565b60006111c3611b27565b9050336001600160a01b03821614611213576040805162461bcd60e51b815260206004820152600e60248201526d2727aa2fa32927a6afa0a226a4a760911b604482015290519081900360640190fd5b50565b60606000611223876114c7565b9050806001600160a01b031663a0c76a9688888888886040518663ffffffff1660e01b815260040180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156112d35781810151838201526020016112bb565b50505050905090810190601f1680156113005780820380516001836020036101000a031916815260200191505b50965050505050505060006040518083038186803b15801561132157600080fd5b505afa158015611335573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561135e57600080fd5b8101908080516040519392919084600160201b82111561137d57600080fd5b90830190602082018581111561139257600080fd5b8251600160201b8111828201881017156113ab57600080fd5b82525081516020918201929091019080838360005b838110156113d85781810151838201526020016113c0565b50505050905090810190601f1680156114055780820380516001836020036101000a031916815260200191505b5060405250505091505095945050505050565b600080611424836114c7565b90506001600160a01b03811661143e5760009150506108c1565b806001600160a01b031663a7e28d48846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561149457600080fd5b505afa1580156114a8573d6000803e3d6000fd5b505050506040513d60208110156114be57600080fd5b50519392505050565b6001600160a01b0380821660009081526003602052604090205416806114f557506004546001600160a01b03165b6001600160a01b0381166001148061151c575061151a816001600160a01b0316611627565b155b156108c1575060006108c1565b606061153a88888888888888611b4c565b98975050505050505050565b600061155585858585336109d4565b95945050505050565b6003602052600090815260409020546001600160a01b031681565b6002546001600160a01b031681565b6006546001600160a01b031681565b6001600160e01b031981166301ffc9a760e01b14919050565b6001600160a01b038216156115f9576040805162461bcd60e51b815260206004820152600a6024820152692120a22fa927aaaa22a960b11b604482015290519081900360640190fd5b6116038383611da1565b600480546001600160a01b0319166001600160a01b03929092169190911790555050565b3b151590565b60008551875114611674576040805162461bcd60e51b815260206004820152600c60248201526b0aea49e9c8ebe988a9c8ea8960a31b604482015290519081900360640190fd5b60005b87518110156119755786818151811061168c57fe5b6020026020010151600360008a84815181106116a457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055508681815181106116fc57fe5b60200260200101516001600160a01b031688828151811061171957fe5b60200260200101516001600160a01b03167f812ca95fe4492a9e2d1f2723c2c40c03a60a27b059581ae20ac4e4d73bfba35460405160405180910390a360006001600160a01b031687828151811061176d57fe5b60200260200101516001600160a01b0316141580156117b2575060016001600160a01b031687828151811061179e57fe5b60200260200101516001600160a01b031614155b1561196d5760006001600160a01b03168782815181106117ce57fe5b60200260200101516001600160a01b031663a7e28d488a84815181106117f057fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561183e57600080fd5b505afa158015611852573d6000803e3d6000fd5b505050506040513d602081101561186857600080fd5b50516001600160a01b031614156118c6576040805162461bcd60e51b815260206004820152601c60248201527f544f4b454e5f4e4f545f48414e444c45445f42595f4741544557415900000000604482015290519081900360640190fd5b8681815181106118d257fe5b60200260200101516001600160a01b0316632db09c1c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561191257600080fd5b505afa158015611926573d6000803e3d6000fd5b505050506040513d602081101561193c57600080fd5b5051875188908390811061194c57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101611677565b506060634201f98560e01b8888604051602401808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156119c95781810151838201526020016119b1565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015611a085781810151838201526020016119f0565b50505050905001945050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905061153a600660009054906101000a90046001600160a01b0316600160009054906101000a90046001600160a01b03168534600060405180606001604052808b81526020018d81526020018c81525087611b08565b606083838360405160200180846001600160a01b03166001600160a01b0316815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f9093018316909401848103909201845252509998505050505050505050565b600061153a8888888888886000015189602001518a604001518a611e6d565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60606000611b59896114c7565b90506060611b68338686611a9e565b604080516001600160a01b0385811682529151929350818c169233928e16917f85291dff2161a93c2f12c819d31889c96c63042116f5bc5a205aa701c2c429f5919081900360200190a4816001600160a01b031663d2ce7d65348c8c8c8c8c886040518863ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b0316815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611c56578181015183820152602001611c3e565b50505050905090810190601f168015611c835780820380516001836020036101000a031916815260200191505b509750505050505050506000604051808303818588803b158015611ca657600080fd5b505af1158015611cba573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526020811015611ce457600080fd5b8101908080516040519392919084600160201b821115611d0357600080fd5b908301906020820185811115611d1857600080fd5b8251600160201b811182820188101715611d3157600080fd5b82525081516020918201929091019080838360005b83811015611d5e578181015183820152602001611d46565b50505050905090810190601f168015611d8b5780820380516001836020036101000a031916815260200191505b5060405250505092505050979650505050505050565b6001600160a01b038216611df2576040805162461bcd60e51b81526020600482015260136024820152721253959053125117d0d3d55395115494105495606a1b604482015290519081900360640190fd5b6001546001600160a01b031615611e3f576040805162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015290519081900360640190fd5b600180546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055565b6000611e818a8a8a8b8b8b8b8b8b8b611e8f565b9a9950505050505050505050565b6000808b6001600160a01b031663679b6ded898d8a8a8f8f8c8c8c6040518a63ffffffff1660e01b815260040180896001600160a01b03166001600160a01b03168152602001888152602001878152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611f56578181015183820152602001611f3e565b50505050905090810190601f168015611f835780820380516001836020036101000a031916815260200191505b5099505050505050505050506020604051808303818588803b158015611fa857600080fd5b505af1158015611fbc573d6000803e3d6000fd5b50505050506040513d6020811015611fd357600080fd5b81019080805190602001909291905050509050808b6001600160a01b03168a6001600160a01b03167fc1d1490cf25c3b40d600dfb27c7680340ed1ab901b7e8f3551280968a3b372b0866040518080602001828103825283818151815260200191508051906020019080838360005b8381101561205a578181015183820152602001612042565b50505050905090810190601f1680156120875780820380516001836020036101000a031916815260200191505b509250505060405180910390a49b9a505050505050505050505056fea2646970667358221220c4a157f9a39440a0ea612bf7652aa5411a0f46a2320a00c81134f98dfb9f2fc664736f6c634300060b0033
Deployed Bytecode
0x6080604052600436106101355760003560e01c80638da5cb5b116100ab578063bda009fe1161006f578063bda009fe14610737578063d2ce7d651461076a578063dd61456914610804578063ed08fdc61461083c578063f887ea401461086f578063fb0e722b1461088457610135565b80638da5cb5b146105ec57806393e59dc11461060157806395fcea7814610616578063a0c76a961461062b578063a7e28d481461070457610135565b80632db09c1c116100fd5780632db09c1c146102915780632e567b36146102a657806347466f981461033c5780634fb1a07b1461036f5780635625a95214610486578063658b53f4146104be57610135565b806301ffc9a71461013a578063032958021461018257806313af4035146101b35780631459457a146101e85780632d67b72d1461023d575b600080fd5b34801561014657600080fd5b5061016e6004803603602081101561015d57600080fd5b50356001600160e01b031916610899565b604080519115158252519081900360200190f35b34801561018e57600080fd5b506101976108c6565b604080516001600160a01b039092168252519081900360200190f35b3480156101bf57600080fd5b506101e6600480360360208110156101d657600080fd5b50356001600160a01b03166108d5565b005b3480156101f457600080fd5b506101e6600480360360a081101561020b57600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101358216916080909101351661098e565b61027f600480360360a081101561025357600080fd5b506001600160a01b038135811691602081013591604082013591606081013591608090910135166109d4565b60408051918252519081900360200190f35b34801561029d57600080fd5b50610197610c31565b6101e6600480360360a08110156102bc57600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b8111156102fe57600080fd5b82018360208201111561031057600080fd5b803590602001918460018302840111600160201b8311171561033157600080fd5b509092509050610c40565b34801561034857600080fd5b506101e66004803603602081101561035f57600080fd5b50356001600160a01b0316610c84565b610411600480360360e081101561038557600080fd5b6001600160a01b038235811692602081013582169260408201359092169160608201359160808101359160a0820135919081019060e0810160c0820135600160201b8111156103d357600080fd5b8201836020820111156103e557600080fd5b803590602001918460018302840111600160201b8311171561040657600080fd5b509092509050610d27565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561044b578181015183820152602001610433565b50505050905090810190601f1680156104785780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61027f6004803603608081101561049c57600080fd5b506001600160a01b038135169060208101359060408101359060600135610f97565b61027f600480360360a08110156104d457600080fd5b810190602081018135600160201b8111156104ee57600080fd5b82018360208201111561050057600080fd5b803590602001918460208302840111600160201b8311171561052157600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561057057600080fd5b82018360208201111561058257600080fd5b803590602001918460208302840111600160201b831117156105a357600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060208101359060400135611134565b3480156105f857600080fd5b5061019761119b565b34801561060d57600080fd5b506101976111aa565b34801561062257600080fd5b506101e66111b9565b34801561063757600080fd5b50610411600480360360a081101561064e57600080fd5b6001600160a01b03823581169260208101358216926040820135909216916060820135919081019060a081016080820135600160201b81111561069057600080fd5b8201836020820111156106a257600080fd5b803590602001918460018302840111600160201b831117156106c357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611216945050505050565b34801561071057600080fd5b506101976004803603602081101561072757600080fd5b50356001600160a01b0316611418565b34801561074357600080fd5b506101976004803603602081101561075a57600080fd5b50356001600160a01b03166114c7565b610411600480360360c081101561078057600080fd5b6001600160a01b0382358116926020810135909116916040820135916060810135916080820135919081019060c0810160a0820135600160201b8111156107c657600080fd5b8201836020820111156107d857600080fd5b803590602001918460018302840111600160201b831117156107f957600080fd5b509092509050611529565b61027f6004803603608081101561081a57600080fd5b506001600160a01b038135169060208101359060408101359060600135611546565b34801561084857600080fd5b506101976004803603602081101561085f57600080fd5b50356001600160a01b031661155e565b34801561087b57600080fd5b50610197611579565b34801561089057600080fd5b50610197611588565b60006001600160e01b03198216634fb1a07b60e01b14806108be57506108be82611597565b90505b919050565b6004546001600160a01b031681565b6005546001600160a01b03163314610921576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b6001600160a01b03811661096c576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b604482015290519081900360640190fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b61099a826000866115b0565b600580546001600160a01b039687166001600160a01b03199182161790915560008054821690556006805492909616911617909355505050565b600061a4b160ff16336001600160a01b0316638e5f5ad16040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1557600080fd5b505afa158015610a29573d6000803e3d6000fd5b505050506040513d6020811015610a3f57600080fd5b505160ff1614610a88576040805162461bcd60e51b815260206004820152600f60248201526e1393d517d0549097d1539050931151608a1b604482015290519081900360640190fd5b610a9a866001600160a01b0316611627565b610add576040805162461bcd60e51b815260206004820152600f60248201526e1393d517d513d7d0d3d395149050d5608a1b604482015290519081900360640190fd5b6000610ae8336114c7565b90506001600160a01b03811615801590610b1057506004546001600160a01b03828116911614155b15610b7b57866001600160a01b0316816001600160a01b031614610b7b576040805162461bcd60e51b815260206004820152601b60248201527f4e4f5f5550444154455f544f5f444946464552454e545f414444520000000000604482015290519081900360640190fd5b604080516001808252818301909252606091602080830190803683370190505090503381600081518110610bab57fe5b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526060918160200160208202803683370190505090508881600081518110610bf657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050610c2482828a8a8a8a61162d565b9998505050505050505050565b6001546001600160a01b031681565b6040805162461bcd60e51b815260206004820152601460248201527327a7262cafa7aaaa2127aaa7222fa927aaaa22a960611b604482015290519081900360640190fd5b6000546001600160a01b03163314610cd3576040805162461bcd60e51b815260206004820152600d60248201526c1393d517d19493d357d31254d5609a1b604482015290519081900360640190fd5b600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f37389c47920d5cc3229678a0205d0455002c07541a4139ebdce91ac2274657779181900360200190a150565b60606000610d348a6114c7565b90506060610d43338686611a9e565b604080516001600160a01b0385811682529151929350818c169233928f16917f85291dff2161a93c2f12c819d31889c96c63042116f5bc5a205aa701c2c429f5919081900360200190a4816001600160a01b0316634fb1a07b348d8d8d8d8d8d896040518963ffffffff1660e01b815260040180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b0316815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610e4a578181015183820152602001610e32565b50505050905090810190601f168015610e775780820380516001836020036101000a031916815260200191505b50985050505050505050506000604051808303818588803b158015610e9b57600080fd5b505af1158015610eaf573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526020811015610ed957600080fd5b8101908080516040519392919084600160201b821115610ef857600080fd5b908301906020820185811115610f0d57600080fd5b8251600160201b811182820188101715610f2657600080fd5b82525081516020918201929091019080838360005b83811015610f53578181015183820152602001610f3b565b50505050905090810190601f168015610f805780820380516001836020036101000a031916815260200191505b506040525050509250505098975050505050505050565b6005546000906001600160a01b03163314610fe6576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b600480546001600160a01b0387166001600160a01b0319909116811790915560408051918252517f3a8f8eb961383a94d41d193e16a3af73eaddfd5764a4c640257323a1603ac3319181900360200190a160006001600160a01b038616156110b057856001600160a01b0316632db09c1c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561108157600080fd5b505afa158015611095573d6000803e3d6000fd5b505050506040513d60208110156110ab57600080fd5b505190505b604080516001600160a01b038084166024808401919091528351808403909101815260449092018352602082810180516001600160e01b031663f7c9362f60e01b17905260065460015485516060810187528981529283018b905294820189905292936111299383169216903390349060009087611b08565b979650505050505050565b6005546000906001600160a01b03163314611183576040805162461bcd60e51b815260206004820152600a60248201526927a7262cafa7aba722a960b11b604482015290519081900360640190fd5b61119186868686863361162d565b9695505050505050565b6005546001600160a01b031681565b6000546001600160a01b031681565b60006111c3611b27565b9050336001600160a01b03821614611213576040805162461bcd60e51b815260206004820152600e60248201526d2727aa2fa32927a6afa0a226a4a760911b604482015290519081900360640190fd5b50565b60606000611223876114c7565b9050806001600160a01b031663a0c76a9688888888886040518663ffffffff1660e01b815260040180866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156112d35781810151838201526020016112bb565b50505050905090810190601f1680156113005780820380516001836020036101000a031916815260200191505b50965050505050505060006040518083038186803b15801561132157600080fd5b505afa158015611335573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561135e57600080fd5b8101908080516040519392919084600160201b82111561137d57600080fd5b90830190602082018581111561139257600080fd5b8251600160201b8111828201881017156113ab57600080fd5b82525081516020918201929091019080838360005b838110156113d85781810151838201526020016113c0565b50505050905090810190601f1680156114055780820380516001836020036101000a031916815260200191505b5060405250505091505095945050505050565b600080611424836114c7565b90506001600160a01b03811661143e5760009150506108c1565b806001600160a01b031663a7e28d48846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561149457600080fd5b505afa1580156114a8573d6000803e3d6000fd5b505050506040513d60208110156114be57600080fd5b50519392505050565b6001600160a01b0380821660009081526003602052604090205416806114f557506004546001600160a01b03165b6001600160a01b0381166001148061151c575061151a816001600160a01b0316611627565b155b156108c1575060006108c1565b606061153a88888888888888611b4c565b98975050505050505050565b600061155585858585336109d4565b95945050505050565b6003602052600090815260409020546001600160a01b031681565b6002546001600160a01b031681565b6006546001600160a01b031681565b6001600160e01b031981166301ffc9a760e01b14919050565b6001600160a01b038216156115f9576040805162461bcd60e51b815260206004820152600a6024820152692120a22fa927aaaa22a960b11b604482015290519081900360640190fd5b6116038383611da1565b600480546001600160a01b0319166001600160a01b03929092169190911790555050565b3b151590565b60008551875114611674576040805162461bcd60e51b815260206004820152600c60248201526b0aea49e9c8ebe988a9c8ea8960a31b604482015290519081900360640190fd5b60005b87518110156119755786818151811061168c57fe5b6020026020010151600360008a84815181106116a457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055508681815181106116fc57fe5b60200260200101516001600160a01b031688828151811061171957fe5b60200260200101516001600160a01b03167f812ca95fe4492a9e2d1f2723c2c40c03a60a27b059581ae20ac4e4d73bfba35460405160405180910390a360006001600160a01b031687828151811061176d57fe5b60200260200101516001600160a01b0316141580156117b2575060016001600160a01b031687828151811061179e57fe5b60200260200101516001600160a01b031614155b1561196d5760006001600160a01b03168782815181106117ce57fe5b60200260200101516001600160a01b031663a7e28d488a84815181106117f057fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561183e57600080fd5b505afa158015611852573d6000803e3d6000fd5b505050506040513d602081101561186857600080fd5b50516001600160a01b031614156118c6576040805162461bcd60e51b815260206004820152601c60248201527f544f4b454e5f4e4f545f48414e444c45445f42595f4741544557415900000000604482015290519081900360640190fd5b8681815181106118d257fe5b60200260200101516001600160a01b0316632db09c1c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561191257600080fd5b505afa158015611926573d6000803e3d6000fd5b505050506040513d602081101561193c57600080fd5b5051875188908390811061194c57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101611677565b506060634201f98560e01b8888604051602401808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156119c95781810151838201526020016119b1565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015611a085781810151838201526020016119f0565b50505050905001945050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905061153a600660009054906101000a90046001600160a01b0316600160009054906101000a90046001600160a01b03168534600060405180606001604052808b81526020018d81526020018c81525087611b08565b606083838360405160200180846001600160a01b03166001600160a01b0316815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f9093018316909401848103909201845252509998505050505050505050565b600061153a8888888888886000015189602001518a604001518a611e6d565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60606000611b59896114c7565b90506060611b68338686611a9e565b604080516001600160a01b0385811682529151929350818c169233928e16917f85291dff2161a93c2f12c819d31889c96c63042116f5bc5a205aa701c2c429f5919081900360200190a4816001600160a01b031663d2ce7d65348c8c8c8c8c886040518863ffffffff1660e01b815260040180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b0316815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611c56578181015183820152602001611c3e565b50505050905090810190601f168015611c835780820380516001836020036101000a031916815260200191505b509750505050505050506000604051808303818588803b158015611ca657600080fd5b505af1158015611cba573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f191682016040526020811015611ce457600080fd5b8101908080516040519392919084600160201b821115611d0357600080fd5b908301906020820185811115611d1857600080fd5b8251600160201b811182820188101715611d3157600080fd5b82525081516020918201929091019080838360005b83811015611d5e578181015183820152602001611d46565b50505050905090810190601f168015611d8b5780820380516001836020036101000a031916815260200191505b5060405250505092505050979650505050505050565b6001600160a01b038216611df2576040805162461bcd60e51b81526020600482015260136024820152721253959053125117d0d3d55395115494105495606a1b604482015290519081900360640190fd5b6001546001600160a01b031615611e3f576040805162461bcd60e51b815260206004820152600c60248201526b1053149150511657d253925560a21b604482015290519081900360640190fd5b600180546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055565b6000611e818a8a8a8b8b8b8b8b8b8b611e8f565b9a9950505050505050505050565b6000808b6001600160a01b031663679b6ded898d8a8a8f8f8c8c8c6040518a63ffffffff1660e01b815260040180896001600160a01b03166001600160a01b03168152602001888152602001878152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611f56578181015183820152602001611f3e565b50505050905090810190601f168015611f835780820380516001836020036101000a031916815260200191505b5099505050505050505050506020604051808303818588803b158015611fa857600080fd5b505af1158015611fbc573d6000803e3d6000fd5b50505050506040513d6020811015611fd357600080fd5b81019080805190602001909291905050509050808b6001600160a01b03168a6001600160a01b03167fc1d1490cf25c3b40d600dfb27c7680340ed1ab901b7e8f3551280968a3b372b0866040518080602001828103825283818151815260200191508051906020019080838360005b8381101561205a578181015183820152602001612042565b50505050905090810190601f1680156120875780820380516001836020036101000a031916815260200191505b509250505060405180910390a49b9a505050505050505050505056fea2646970667358221220c4a157f9a39440a0ea612bf7652aa5411a0f46a2320a00c81134f98dfb9f2fc664736f6c634300060b0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.