Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
To
|
Amount
|
||
|---|---|---|---|---|---|---|---|
| Create Retryable... | 9767711 | 5 days ago | 0.0800021 ETH | ||||
| Create Retryable... | 9767711 | 5 days ago | 0.0100021 ETH | ||||
| Create Retryable... | 9767711 | 5 days ago | 0.0247021 ETH | ||||
| Create Retryable... | 9767711 | 5 days ago | 0.0100021 ETH | ||||
| Perform | 9767711 | 5 days ago | 0.1247084 ETH | ||||
| Create Retryable... | 9767507 | 5 days ago | 0.0800021 ETH | ||||
| Create Retryable... | 9767507 | 5 days ago | 0.0100021 ETH | ||||
| Create Retryable... | 9767507 | 5 days ago | 0.0247021 ETH | ||||
| Create Retryable... | 9767507 | 5 days ago | 0.0100021 ETH | ||||
| Perform | 9767507 | 5 days ago | 0.1247084 ETH | ||||
| Create Retryable... | 9608076 | 28 days ago | 0.0800021 ETH | ||||
| Create Retryable... | 9608076 | 28 days ago | 0.0100021 ETH | ||||
| Create Retryable... | 9608076 | 28 days ago | 0.0247021 ETH | ||||
| Create Retryable... | 9608076 | 28 days ago | 0.0100021 ETH | ||||
| Perform | 9608076 | 28 days ago | 0.1247084 ETH | ||||
| Create Retryable... | 9580482 | 32 days ago | 0.0800021 ETH | ||||
| Create Retryable... | 9580482 | 32 days ago | 0.0100021 ETH | ||||
| Create Retryable... | 9580482 | 32 days ago | 0.0247021 ETH | ||||
| Create Retryable... | 9580482 | 32 days ago | 0.0100021 ETH | ||||
| Perform | 9580482 | 32 days ago | 0.1247084 ETH | ||||
| Create Retryable... | 9521841 | 40 days ago | 0.0800021 ETH | ||||
| Create Retryable... | 9521841 | 40 days ago | 0.0100021 ETH | ||||
| Create Retryable... | 9521841 | 40 days ago | 0.0247021 ETH | ||||
| Create Retryable... | 9521841 | 40 days ago | 0.0100021 ETH | ||||
| Perform | 9521841 | 40 days ago | 0.1247084 ETH |
Loading...
Loading
Loading...
Loading
Contract Name:
DeployHelper
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {IInbox} from "../bridge/IInbox.sol";
import {IInboxBase} from "../bridge/IInboxBase.sol";
import {IERC20Inbox} from "../bridge/ERC20Inbox.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/// @notice Helper contract for deploying some keyless deployment to Arbitrum using delayed inbox
contract DeployHelper {
// All payload are padded with 0x04 (ArbOS L2MessageKind_SignedTx Type)
// Nick's CREATE2 Deterministic Deployment Proxy
// https://github.com/Arachnid/deterministic-deployment-proxy
address public constant NICK_CREATE2_DEPLOYER = 0x3fAB184622Dc19b6109349B94811493BF2a45362;
uint256 public constant NICK_CREATE2_VALUE = 0.01 ether;
bytes public constant NICK_CREATE2_PAYLOAD =
hex"04f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222";
// ERC-2470 Singleton Factory
// https://eips.ethereum.org/EIPS/eip-2470
address public constant ERC2470_DEPLOYER = 0xBb6e024b9cFFACB947A71991E386681B1Cd1477D;
uint256 public constant ERC2470_VALUE = 0.0247 ether;
bytes public constant ERC2470_PAYLOAD =
hex"04f9016c8085174876e8008303c4d88080b90154608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c634300060200331b83247000822470";
// Zoltu's CREATE2 Deterministic Deployment Proxy
// https://github.com/Zoltu/deterministic-deployment-proxy
address public constant ZOLTU_CREATE2_DEPLOYER = 0x4c8D290a1B368ac4728d83a9e8321fC3af2b39b1;
uint256 public constant ZOLTU_VALUE = 0.01 ether;
bytes public constant ZOLTU_CREATE2_PAYLOAD =
hex"04f87e8085174876e800830186a08080ad601f80600e600039806000f350fe60003681823780368234f58015156014578182fd5b80825250506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222";
// ERC-1820: Pseudo-introspection Registry Contract
// https://eips.ethereum.org/EIPS/eip-1820
address public constant ERC1820_DEPLOYER = 0xa990077c3205cbDf861e17Fa532eeB069cE9fF96;
uint256 public constant ERC1820_VALUE = 0.08 ether;
bytes public constant ERC1820_PAYLOAD =
hex"04f90a388085174876e800830c35008080b909e5608060405234801561001057600080fd5b506109c5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063a41e7d5111610078578063a41e7d51146101d4578063aabbb8ca1461020a578063b705676514610236578063f712f3e814610280576100a5565b806329965a1d146100aa5780633d584063146100e25780635df8122f1461012457806365ba36c114610152575b600080fd5b6100e0600480360360608110156100c057600080fd5b50600160a060020a038135811691602081013591604090910135166102b6565b005b610108600480360360208110156100f857600080fd5b5035600160a060020a0316610570565b60408051600160a060020a039092168252519081900360200190f35b6100e06004803603604081101561013a57600080fd5b50600160a060020a03813581169160200135166105bc565b6101c26004803603602081101561016857600080fd5b81019060208101813564010000000081111561018357600080fd5b82018360208201111561019557600080fd5b803590602001918460018302840111640100000000831117156101b757600080fd5b5090925090506106b3565b60408051918252519081900360200190f35b6100e0600480360360408110156101ea57600080fd5b508035600160a060020a03169060200135600160e060020a0319166106ee565b6101086004803603604081101561022057600080fd5b50600160a060020a038135169060200135610778565b61026c6004803603604081101561024c57600080fd5b508035600160a060020a03169060200135600160e060020a0319166107ef565b604080519115158252519081900360200190f35b61026c6004803603604081101561029657600080fd5b508035600160a060020a03169060200135600160e060020a0319166108aa565b6000600160a060020a038416156102cd57836102cf565b335b9050336102db82610570565b600160a060020a031614610339576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b6103428361092a565b15610397576040805160e560020a62461bcd02815260206004820152601a60248201527f4d757374206e6f7420626520616e204552433136352068617368000000000000604482015290519081900360640190fd5b600160a060020a038216158015906103b85750600160a060020a0382163314155b156104ff5760405160200180807f455243313832305f4143434550545f4d4147494300000000000000000000000081525060140190506040516020818303038152906040528051906020012082600160a060020a031663249cb3fa85846040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083815260200182600160a060020a0316600160a060020a031681526020019250505060206040518083038186803b15801561047e57600080fd5b505afa158015610492573d6000803e3d6000fd5b505050506040513d60208110156104a857600080fd5b5051146104ff576040805160e560020a62461bcd02815260206004820181905260248201527f446f6573206e6f7420696d706c656d656e742074686520696e74657266616365604482015290519081900360640190fd5b600160a060020a03818116600081815260208181526040808320888452909152808220805473ffffffffffffffffffffffffffffffffffffffff19169487169485179055518692917f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db15391a450505050565b600160a060020a03818116600090815260016020526040812054909116151561059a5750806105b7565b50600160a060020a03808216600090815260016020526040902054165b919050565b336105c683610570565b600160a060020a031614610624576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b81600160a060020a031681600160a060020a0316146106435780610646565b60005b600160a060020a03838116600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169585169590951790945592519184169290917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43509190a35050565b600082826040516020018083838082843780830192505050925050506040516020818303038152906040528051906020012090505b92915050565b6106f882826107ef565b610703576000610705565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b600080600160a060020a038416156107905783610792565b335b905061079d8361092a565b156107c357826107ad82826108aa565b6107b85760006107ba565b815b925050506106e8565b600160a060020a0390811660009081526020818152604080832086845290915290205416905092915050565b6000808061081d857f01ffc9a70000000000000000000000000000000000000000000000000000000061094c565b909250905081158061082d575080155b1561083d576000925050506106e8565b61084f85600160e060020a031961094c565b909250905081158061086057508015155b15610870576000925050506106e8565b61087a858561094c565b909250905060018214801561088f5750806001145b1561089f576001925050506106e8565b506000949350505050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff1615156108f2576108eb83836107ef565b90506106e8565b50600160a060020a03808316600081815260208181526040808320600160e060020a0319871684529091529020549091161492915050565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6040517f01ffc9a7000000000000000000000000000000000000000000000000000000008082526004820183905260009182919060208160248189617530fa90519096909550935050505056fea165627a7a72305820377f4a2d4301ede9949f163f319021a6e9c687c292a5e2b2c4734c126b524e6c00291ba01820182018201820182018201820182018201820182018201820182018201820a01820182018201820182018201820182018201820182018201820182018201820";
uint256 internal constant GASLIMIT = 21_000;
function _fundAndDeploy(
address inbox,
uint256 _value,
address _l2Address,
bytes memory payload,
address _nativeToken,
uint256 maxFeePerGas
) internal {
uint256 submissionCost = IInboxBase(inbox).calculateRetryableSubmissionFee(
0,
block.basefee
);
uint256 feeAmount = _value + submissionCost + GASLIMIT * maxFeePerGas;
// fund the target L2 address
if (_nativeToken != address(0)) {
// calculate the fee amount in the native token's decimals
uint256 feeAmountNativeDenominated = feeAmount;
uint8 decimals = ERC20(_nativeToken).decimals();
if (decimals < 18) {
feeAmountNativeDenominated = feeAmount / (10**(18 - decimals));
// round up if necessary
if (feeAmountNativeDenominated * (10**(18 - decimals)) < feeAmount) {
feeAmountNativeDenominated++;
}
} else if (decimals > 18) {
feeAmountNativeDenominated = feeAmount * (10**(decimals - 18));
}
IERC20Inbox(inbox).createRetryableTicket({
to: _l2Address,
l2CallValue: _value,
maxSubmissionCost: submissionCost,
excessFeeRefundAddress: msg.sender,
callValueRefundAddress: msg.sender,
gasLimit: GASLIMIT,
maxFeePerGas: maxFeePerGas,
tokenTotalFeeAmount: feeAmountNativeDenominated,
data: ""
});
} else {
IInbox(inbox).createRetryableTicket{value: feeAmount}({
to: _l2Address,
l2CallValue: _value,
maxSubmissionCost: submissionCost,
excessFeeRefundAddress: msg.sender,
callValueRefundAddress: msg.sender,
gasLimit: GASLIMIT,
maxFeePerGas: maxFeePerGas,
data: ""
});
}
// send L2 msg to execute deployment transaction
IInboxBase(inbox).sendL2Message(payload);
}
function perform(
address _inbox,
address _nativeToken,
uint256 _maxFeePerGas
) external payable {
_fundAndDeploy(
_inbox,
NICK_CREATE2_VALUE,
NICK_CREATE2_DEPLOYER,
NICK_CREATE2_PAYLOAD,
_nativeToken,
_maxFeePerGas
);
_fundAndDeploy(
_inbox,
ERC2470_VALUE,
ERC2470_DEPLOYER,
ERC2470_PAYLOAD,
_nativeToken,
_maxFeePerGas
);
_fundAndDeploy(
_inbox,
ZOLTU_VALUE,
ZOLTU_CREATE2_DEPLOYER,
ZOLTU_CREATE2_PAYLOAD,
_nativeToken,
_maxFeePerGas
);
_fundAndDeploy(
_inbox,
ERC1820_VALUE,
ERC1820_DEPLOYER,
ERC1820_PAYLOAD,
_nativeToken,
_maxFeePerGas
);
// if paying with ETH refund the caller
if (_nativeToken == address(0)) {
payable(msg.sender).transfer(address(this).balance);
}
}
function getDeploymentTotalCost(IInboxBase inbox, uint256 maxFeePerGas)
public
view
returns (uint256)
{
uint256 submissionCost = inbox.calculateRetryableSubmissionFee(0, block.basefee);
return
NICK_CREATE2_VALUE +
ERC2470_VALUE +
ZOLTU_VALUE +
ERC1820_VALUE +
4 *
(submissionCost + GASLIMIT * maxFeePerGas);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Spend `amount` form the allowance of `owner` toward `spender`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @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
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
import {
DataTooLarge,
GasLimitTooLarge,
InsufficientValue,
InsufficientSubmissionCost,
L1Forked,
NotAllowedOrigin,
NotOrigin,
NotRollupOrOwner,
RetryableData
} from "../libraries/Error.sol";
import "./IInboxBase.sol";
import "./ISequencerInbox.sol";
import "./IBridge.sol";
import "../libraries/AddressAliasHelper.sol";
import "../libraries/DelegateCallAware.sol";
import {
L1MessageType_submitRetryableTx,
L2MessageType_unsignedContractTx,
L2MessageType_unsignedEOATx,
L2_MSG
} from "../libraries/MessageTypes.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol";
/**
* @title Inbox for user and contract originated messages
* @notice Messages created via this inbox are enqueued in the delayed accumulator
* to await inclusion in the SequencerInbox
*/
abstract contract AbsInbox is DelegateCallAware, PausableUpgradeable, IInboxBase {
/// @dev Storage slot with the admin of the contract.
/// This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
bytes32 internal constant _ADMIN_SLOT =
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/// @inheritdoc IInboxBase
IBridge public bridge;
/// @inheritdoc IInboxBase
ISequencerInbox public sequencerInbox;
/// ------------------------------------ allow list start ------------------------------------ ///
/// @inheritdoc IInboxBase
bool public allowListEnabled;
/// @inheritdoc IInboxBase
mapping(address => bool) public isAllowed;
event AllowListAddressSet(address indexed user, bool val);
event AllowListEnabledUpdated(bool isEnabled);
/// @inheritdoc IInboxBase
function setAllowList(address[] memory user, bool[] memory val) external onlyRollupOrOwner {
require(user.length == val.length, "INVALID_INPUT");
for (uint256 i = 0; i < user.length; i++) {
isAllowed[user[i]] = val[i];
emit AllowListAddressSet(user[i], val[i]);
}
}
/// @inheritdoc IInboxBase
function setAllowListEnabled(bool _allowListEnabled) external onlyRollupOrOwner {
require(_allowListEnabled != allowListEnabled, "ALREADY_SET");
allowListEnabled = _allowListEnabled;
emit AllowListEnabledUpdated(_allowListEnabled);
}
/// @dev this modifier checks the tx.origin instead of msg.sender for convenience (ie it allows
/// allowed users to interact with the token bridge without needing the token bridge to be allowList aware).
/// this modifier is not intended to use to be used for security (since this opens the allowList to
/// a smart contract phishing risk).
modifier onlyAllowed() {
// solhint-disable-next-line avoid-tx-origin
if (allowListEnabled && !isAllowed[tx.origin]) revert NotAllowedOrigin(tx.origin);
_;
}
/// ------------------------------------ allow list end ------------------------------------ ///
modifier onlyRollupOrOwner() {
IOwnable rollup = bridge.rollup();
if (msg.sender != address(rollup)) {
address rollupOwner = rollup.owner();
if (msg.sender != rollupOwner) {
revert NotRollupOrOwner(msg.sender, address(rollup), rollupOwner);
}
}
_;
}
// On L1 this should be set to 117964: 90% of Geth's 128KB tx size limit, leaving ~13KB for proving
uint256 public immutable maxDataSize;
uint256 internal immutable deployTimeChainId = block.chainid;
constructor(uint256 _maxDataSize) {
maxDataSize = _maxDataSize;
}
function _chainIdChanged() internal view returns (bool) {
return deployTimeChainId != block.chainid;
}
/// @inheritdoc IInboxBase
function pause() external onlyRollupOrOwner {
_pause();
}
/// @inheritdoc IInboxBase
function unpause() external onlyRollupOrOwner {
_unpause();
}
/* solhint-disable func-name-mixedcase */
function __AbsInbox_init(IBridge _bridge, ISequencerInbox _sequencerInbox)
internal
onlyInitializing
{
bridge = _bridge;
sequencerInbox = _sequencerInbox;
allowListEnabled = false;
__Pausable_init();
}
/// @inheritdoc IInboxBase
function sendL2MessageFromOrigin(bytes calldata messageData)
external
whenNotPaused
onlyAllowed
returns (uint256)
{
if (_chainIdChanged()) revert L1Forked();
// solhint-disable-next-line avoid-tx-origin
if (msg.sender != tx.origin) revert NotOrigin();
if (messageData.length > maxDataSize) revert DataTooLarge(messageData.length, maxDataSize);
uint256 msgNum = _deliverToBridge(L2_MSG, msg.sender, keccak256(messageData), 0);
emit InboxMessageDeliveredFromOrigin(msgNum);
return msgNum;
}
/// @inheritdoc IInboxBase
function sendL2Message(bytes calldata messageData)
external
whenNotPaused
onlyAllowed
returns (uint256)
{
if (_chainIdChanged()) revert L1Forked();
return _deliverMessage(L2_MSG, msg.sender, messageData, 0);
}
/// @inheritdoc IInboxBase
function sendUnsignedTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
uint256 value,
bytes calldata data
) external whenNotPaused onlyAllowed returns (uint256) {
// arbos will discard unsigned tx with gas limit too large
if (gasLimit > type(uint64).max) {
revert GasLimitTooLarge();
}
return
_deliverMessage(
L2_MSG,
msg.sender,
abi.encodePacked(
L2MessageType_unsignedEOATx,
gasLimit,
maxFeePerGas,
nonce,
uint256(uint160(to)),
value,
data
),
0
);
}
/// @inheritdoc IInboxBase
function sendContractTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
address to,
uint256 value,
bytes calldata data
) external whenNotPaused onlyAllowed returns (uint256) {
// arbos will discard unsigned tx with gas limit too large
if (gasLimit > type(uint64).max) {
revert GasLimitTooLarge();
}
return
_deliverMessage(
L2_MSG,
msg.sender,
abi.encodePacked(
L2MessageType_unsignedContractTx,
gasLimit,
maxFeePerGas,
uint256(uint160(to)),
value,
data
),
0
);
}
/// @inheritdoc IInboxBase
function getProxyAdmin() external view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
}
function _createRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 amount,
bytes calldata data
) internal returns (uint256) {
// Ensure the user's deposit alone will make submission succeed.
// In case of native token having non-18 decimals: 'amount' is denominated in native token's decimals. All other
// value params - l2CallValue, maxSubmissionCost and maxFeePerGas are denominated in child chain's native 18 decimals.
uint256 amountToBeMintedOnL2 = _fromNativeTo18Decimals(amount);
if (amountToBeMintedOnL2 < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) {
revert InsufficientValue(
maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas,
amountToBeMintedOnL2
);
}
// if a refund address is a contract, we apply the alias to it
// so that it can access its funds on the L2
// since the beneficiary and other refund addresses don't get rewritten by arb-os
if (AddressUpgradeable.isContract(excessFeeRefundAddress)) {
excessFeeRefundAddress = AddressAliasHelper.applyL1ToL2Alias(excessFeeRefundAddress);
}
if (AddressUpgradeable.isContract(callValueRefundAddress)) {
// this is the beneficiary. be careful since this is the address that can cancel the retryable in the L2
callValueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(callValueRefundAddress);
}
// gas limit is validated to be within uint64 in unsafeCreateRetryableTicket
return
_unsafeCreateRetryableTicket(
to,
l2CallValue,
maxSubmissionCost,
excessFeeRefundAddress,
callValueRefundAddress,
gasLimit,
maxFeePerGas,
amount,
data
);
}
function _unsafeCreateRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 amount,
bytes calldata data
) internal returns (uint256) {
// gas price and limit of 1 should never be a valid input, so instead they are used as
// magic values to trigger a revert in eth calls that surface data without requiring a tx trace
if (gasLimit == 1 || maxFeePerGas == 1)
revert RetryableData(
msg.sender,
to,
l2CallValue,
amount,
maxSubmissionCost,
excessFeeRefundAddress,
callValueRefundAddress,
gasLimit,
maxFeePerGas,
data
);
// arbos will discard retryable with gas limit too large
if (gasLimit > type(uint64).max) {
revert GasLimitTooLarge();
}
uint256 submissionFee = calculateRetryableSubmissionFee(data.length, block.basefee);
if (maxSubmissionCost < submissionFee)
revert InsufficientSubmissionCost(submissionFee, maxSubmissionCost);
return
_deliverMessage(
L1MessageType_submitRetryableTx,
msg.sender,
abi.encodePacked(
uint256(uint160(to)),
l2CallValue,
_fromNativeTo18Decimals(amount),
maxSubmissionCost,
uint256(uint160(excessFeeRefundAddress)),
uint256(uint160(callValueRefundAddress)),
gasLimit,
maxFeePerGas,
data.length,
data
),
amount
);
}
function _deliverMessage(
uint8 _kind,
address _sender,
bytes memory _messageData,
uint256 amount
) internal returns (uint256) {
if (_messageData.length > maxDataSize)
revert DataTooLarge(_messageData.length, maxDataSize);
uint256 msgNum = _deliverToBridge(_kind, _sender, keccak256(_messageData), amount);
emit InboxMessageDelivered(msgNum, _messageData);
return msgNum;
}
function _deliverToBridge(
uint8 kind,
address sender,
bytes32 messageDataHash,
uint256 amount
) internal virtual returns (uint256);
function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee)
public
view
virtual
returns (uint256);
/// @notice get amount of ETH/token to mint on child chain based on provided value.
/// In case of ETH-based rollup this amount will always equal the provided
/// value. In case of ERC20-based rollup where native token has number of
/// decimals different thatn 18, amount will be re-adjusted to reflect 18
/// decimals used for native currency on child chain.
/// @dev provided value has to be less than 'type(uint256).max/10**(18-decimalsIn)'
/// or otherwise it will overflow.
function _fromNativeTo18Decimals(uint256 value) internal view virtual returns (uint256);
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[47] private __gap;
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
import "./AbsInbox.sol";
import "./IERC20Inbox.sol";
import "./IERC20Bridge.sol";
import "../libraries/AddressAliasHelper.sol";
import {L1MessageType_ethDeposit} from "../libraries/MessageTypes.sol";
import {AmountTooLarge} from "../libraries/Error.sol";
import {MAX_UPSCALE_AMOUNT} from "../libraries/Constants.sol";
import {DecimalsConverterHelper} from "../libraries/DecimalsConverterHelper.sol";
import {AddressUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @title Inbox for user and contract originated messages
* @notice Messages created via this inbox are enqueued in the delayed accumulator
* to await inclusion in the SequencerInbox
*/
contract ERC20Inbox is AbsInbox, IERC20Inbox {
using SafeERC20 for IERC20;
constructor(uint256 _maxDataSize) AbsInbox(_maxDataSize) {}
/// @inheritdoc IInboxBase
function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox)
external
initializer
onlyDelegated
{
__AbsInbox_init(_bridge, _sequencerInbox);
// inbox holds native token in transit used to pay for retryable tickets, approve bridge to use it
address nativeToken = IERC20Bridge(address(bridge)).nativeToken();
IERC20(nativeToken).safeApprove(address(bridge), type(uint256).max);
}
/// @inheritdoc IERC20Inbox
function depositERC20(uint256 amount) public whenNotPaused onlyAllowed returns (uint256) {
address dest = msg.sender;
// solhint-disable-next-line avoid-tx-origin
if (AddressUpgradeable.isContract(msg.sender) || tx.origin != msg.sender) {
// isContract check fails if this function is called during a contract's constructor.
dest = AddressAliasHelper.applyL1ToL2Alias(msg.sender);
}
uint256 amountToMintOnL2 = _fromNativeTo18Decimals(amount);
return
_deliverMessage(
L1MessageType_ethDeposit,
msg.sender,
abi.encodePacked(dest, amountToMintOnL2),
amount
);
}
/// @inheritdoc IERC20Inbox
function createRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 tokenTotalFeeAmount,
bytes calldata data
) external whenNotPaused onlyAllowed returns (uint256) {
return
_createRetryableTicket(
to,
l2CallValue,
maxSubmissionCost,
excessFeeRefundAddress,
callValueRefundAddress,
gasLimit,
maxFeePerGas,
tokenTotalFeeAmount,
data
);
}
/// @inheritdoc IERC20Inbox
function unsafeCreateRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 tokenTotalFeeAmount,
bytes calldata data
) public whenNotPaused onlyAllowed returns (uint256) {
return
_unsafeCreateRetryableTicket(
to,
l2CallValue,
maxSubmissionCost,
excessFeeRefundAddress,
callValueRefundAddress,
gasLimit,
maxFeePerGas,
tokenTotalFeeAmount,
data
);
}
/// @inheritdoc IInboxBase
function calculateRetryableSubmissionFee(uint256, uint256)
public
pure
override(AbsInbox, IInboxBase)
returns (uint256)
{
// retryable ticket's submission fee is not charged when ERC20 token is used to pay for fees
return 0;
}
function _deliverToBridge(
uint8 kind,
address sender,
bytes32 messageDataHash,
uint256 tokenAmount
) internal override returns (uint256) {
// Fetch native token from sender if inbox doesn't already hold enough tokens to pay for fees.
// Inbox might have been pre-funded in prior call, ie. as part of token bridging flow.
address nativeToken = IERC20Bridge(address(bridge)).nativeToken();
uint256 inboxNativeTokenBalance = IERC20(nativeToken).balanceOf(address(this));
if (inboxNativeTokenBalance < tokenAmount) {
uint256 diff = tokenAmount - inboxNativeTokenBalance;
IERC20(nativeToken).safeTransferFrom(msg.sender, address(this), diff);
}
return
IERC20Bridge(address(bridge)).enqueueDelayedMessage(
kind,
AddressAliasHelper.applyL1ToL2Alias(sender),
messageDataHash,
tokenAmount
);
}
/// @inheritdoc AbsInbox
function _fromNativeTo18Decimals(uint256 value) internal view override returns (uint256) {
// In order to keep compatibility of child chain's native currency with external 3rd party tooling we
// expect 18 decimals to be always used for native currency. If native token uses different number of
// decimals then here it will be normalized to 18. Keep in mind, when withdrawing from child chain back
// to parent chain then the amount has to match native token's granularity, otherwise it will be rounded
// down.
uint8 nativeTokenDecimals = IERC20Bridge(address(bridge)).nativeTokenDecimals();
// Also make sure that inflated amount does not overflow uint256
if (nativeTokenDecimals < 18) {
if (value > MAX_UPSCALE_AMOUNT) {
revert AmountTooLarge(value);
}
}
return DecimalsConverterHelper.adjustDecimals(value, nativeTokenDecimals, 18);
}
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IOwnable.sol";
interface IBridge {
/// @dev This is an instruction to offchain readers to inform them where to look
/// for sequencer inbox batch data. This is not the type of data (eg. das, brotli encoded, or blob versioned hash)
/// and this enum is not used in the state transition function, rather it informs an offchain
/// reader where to find the data so that they can supply it to the replay binary
enum BatchDataLocation {
/// @notice The data can be found in the transaction call data
TxInput,
/// @notice The data can be found in an event emitted during the transaction
SeparateBatchEvent,
/// @notice This batch contains no data
NoData,
/// @notice The data can be found in the 4844 data blobs on this transaction
Blob
}
struct TimeBounds {
uint64 minTimestamp;
uint64 maxTimestamp;
uint64 minBlockNumber;
uint64 maxBlockNumber;
}
event MessageDelivered(
uint256 indexed messageIndex,
bytes32 indexed beforeInboxAcc,
address inbox,
uint8 kind,
address sender,
bytes32 messageDataHash,
uint256 baseFeeL1,
uint64 timestamp
);
event BridgeCallTriggered(
address indexed outbox,
address indexed to,
uint256 value,
bytes data
);
event InboxToggle(address indexed inbox, bool enabled);
event OutboxToggle(address indexed outbox, bool enabled);
event SequencerInboxUpdated(address newSequencerInbox);
event RollupUpdated(address rollup);
function allowedDelayedInboxList(uint256) external returns (address);
function allowedOutboxList(uint256) external returns (address);
/// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
function delayedInboxAccs(uint256) external view returns (bytes32);
/// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
function sequencerInboxAccs(uint256) external view returns (bytes32);
function rollup() external view returns (IOwnable);
function sequencerInbox() external view returns (address);
function activeOutbox() external view returns (address);
function allowedDelayedInboxes(address inbox) external view returns (bool);
function allowedOutboxes(address outbox) external view returns (bool);
function sequencerReportedSubMessageCount() external view returns (uint256);
function executeCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool success, bytes memory returnData);
function delayedMessageCount() external view returns (uint256);
function sequencerMessageCount() external view returns (uint256);
// ---------- onlySequencerInbox functions ----------
function enqueueSequencerMessage(
bytes32 dataHash,
uint256 afterDelayedMessagesRead,
uint256 prevMessageCount,
uint256 newMessageCount
)
external
returns (
uint256 seqMessageIndex,
bytes32 beforeAcc,
bytes32 delayedAcc,
bytes32 acc
);
/**
* @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type
* This is done through a separate function entrypoint instead of allowing the sequencer inbox
* to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
* every delayed inbox or every sequencer inbox call.
*/
function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
external
returns (uint256 msgNum);
// ---------- onlyRollupOrOwner functions ----------
function setSequencerInbox(address _sequencerInbox) external;
function setDelayedInbox(address inbox, bool enabled) external;
function setOutbox(address inbox, bool enabled) external;
function updateRollupAddress(IOwnable _rollup) external;
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
interface IDelayedMessageProvider {
/// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
event InboxMessageDelivered(uint256 indexed messageNum, bytes data);
/// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
/// same as InboxMessageDelivered but the batch data is available in tx.input
event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IOwnable.sol";
import "./IBridge.sol";
interface IERC20Bridge is IBridge {
/**
* @dev token that is escrowed in bridge on L1 side and minted on L2 as native currency.
* Fees are paid in this token. There are certain restrictions on the native token:
* - The token can't be rebasing or have a transfer fee
* - The token must only be transferrable via a call to the token address itself
* - The token must only be able to set allowance via a call to the token address itself
* - The token must not have a callback on transfer, and more generally a user must not be able to make a transfer to themselves revert
*/
function nativeToken() external view returns (address);
/**
* @dev number of decimals used by the native token
* This is set on bridge initialization using nativeToken.decimals()
* If the token does not have decimals() method, we assume it have 0 decimals
*/
function nativeTokenDecimals() external view returns (uint8);
/**
* @dev Enqueue a message in the delayed inbox accumulator.
* These messages are later sequenced in the SequencerInbox, either
* by the sequencer as part of a normal batch, or by force inclusion.
*/
function enqueueDelayedMessage(
uint8 kind,
address sender,
bytes32 messageDataHash,
uint256 tokenFeeAmount
) external returns (uint256);
// ---------- initializer ----------
function initialize(IOwnable rollup_, address nativeToken_) external;
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IInboxBase.sol";
interface IERC20Inbox is IInboxBase {
/**
* @notice Deposit native token from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract
* @dev This does not trigger the fallback function when receiving in the L2 side.
* Look into retryable tickets if you are interested in this functionality.
* @dev This function should not be called inside contract constructors
*/
function depositERC20(uint256 amount) external returns (uint256);
/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev all tokenTotalFeeAmount will be deposited to callValueRefundAddress on L2
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
* @dev In case of native token having non-18 decimals: tokenTotalFeeAmount is denominated in native token's decimals. All other value params - l2CallValue, maxSubmissionCost and maxFeePerGas are denominated in child chain's native 18 decimals.
* @param to destination L2 contract address
* @param l2CallValue call value for retryable L2 message
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param excessFeeRefundAddress the address which receives the difference between execution fee paid and the actual execution cost. In case this address is a contract, funds will be received in its alias on L2.
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled. In case this address is a contract, funds will be received in its alias on L2.
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param tokenTotalFeeAmount amount of fees to be deposited in native token to cover for retryable ticket cost
* @param data ABI encoded data of L2 message
* @return unique message number of the retryable transaction
*/
function createRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 tokenTotalFeeAmount,
bytes calldata data
) external returns (uint256);
/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds
* come from the deposit alone, rather than falling back on the user's L2 balance
* @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).
* createRetryableTicket method is the recommended standard.
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
* @param to destination L2 contract address
* @param l2CallValue call value for retryable L2 message
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param excessFeeRefundAddress the address which receives the difference between execution fee paid and the actual execution cost
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param tokenTotalFeeAmount amount of fees to be deposited in native token to cover for retryable ticket cost
* @param data ABI encoded data of L2 message
* @return unique message number of the retryable transaction
*/
function unsafeCreateRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 tokenTotalFeeAmount,
bytes calldata data
) external returns (uint256);
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IBridge.sol";
import "./IInboxBase.sol";
interface IInbox is IInboxBase {
function sendL1FundedUnsignedTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
bytes calldata data
) external payable returns (uint256);
function sendL1FundedContractTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
address to,
bytes calldata data
) external payable returns (uint256);
/**
* @dev This method can only be called upon L1 fork and will not alias the caller
* This method will revert if not called from origin
*/
function sendL1FundedUnsignedTransactionToFork(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
bytes calldata data
) external payable returns (uint256);
/**
* @dev This method can only be called upon L1 fork and will not alias the caller
* This method will revert if not called from origin
*/
function sendUnsignedTransactionToFork(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
uint256 value,
bytes calldata data
) external returns (uint256);
/**
* @notice Send a message to initiate L2 withdrawal
* @dev This method can only be called upon L1 fork and will not alias the caller
* This method will revert if not called from origin
*/
function sendWithdrawEthToFork(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
uint256 value,
address withdrawTo
) external returns (uint256);
/**
* @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract
* @dev This does not trigger the fallback function when receiving in the L2 side.
* Look into retryable tickets if you are interested in this functionality.
* @dev This function should not be called inside contract constructors
*/
function depositEth() external payable returns (uint256);
/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev all msg.value will deposited to callValueRefundAddress on L2
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
* @param to destination L2 contract address
* @param l2CallValue call value for retryable L2 message
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param excessFeeRefundAddress the address which receives the difference between execution fee paid and the actual execution cost. In case this address is a contract, funds will be received in its alias on L2.
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled. In case this address is a contract, funds will be received in its alias on L2.
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param data ABI encoded data of L2 message
* @return unique message number of the retryable transaction
*/
function createRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes calldata data
) external payable returns (uint256);
/**
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
* @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds
* come from the deposit alone, rather than falling back on the user's L2 balance
* @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).
* createRetryableTicket method is the recommended standard.
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
* @param to destination L2 contract address
* @param l2CallValue call value for retryable L2 message
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
* @param excessFeeRefundAddress the address which receives the difference between execution fee paid and the actual execution cost
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
* @param data ABI encoded data of L2 message
* @return unique message number of the retryable transaction
*/
function unsafeCreateRetryableTicket(
address to,
uint256 l2CallValue,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes calldata data
) external payable returns (uint256);
// ---------- initializer ----------
/**
* @dev function to be called one time during the inbox upgrade process
* this is used to fix the storage slots
*/
function postUpgradeInit(IBridge _bridge) external;
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
import "./IBridge.sol";
import "./IDelayedMessageProvider.sol";
import "./ISequencerInbox.sol";
interface IInboxBase is IDelayedMessageProvider {
function bridge() external view returns (IBridge);
function sequencerInbox() external view returns (ISequencerInbox);
function maxDataSize() external view returns (uint256);
/**
* @notice Send a generic L2 message to the chain
* @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input
* @param messageData Data of the message being sent
*/
function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256);
/**
* @notice Send a generic L2 message to the chain
* @dev This method can be used to send any type of message that doesn't require L1 validation
* @param messageData Data of the message being sent
*/
function sendL2Message(bytes calldata messageData) external returns (uint256);
function sendUnsignedTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
uint256 nonce,
address to,
uint256 value,
bytes calldata data
) external returns (uint256);
function sendContractTransaction(
uint256 gasLimit,
uint256 maxFeePerGas,
address to,
uint256 value,
bytes calldata data
) external returns (uint256);
/**
* @notice Get the L1 fee for submitting a retryable
* @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
* @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
* @param dataLength The length of the retryable's calldata, in bytes
* @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used
*/
function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee)
external
view
returns (uint256);
// ---------- onlyRollupOrOwner functions ----------
/// @notice pauses all inbox functionality
function pause() external;
/// @notice unpauses all inbox functionality
function unpause() external;
/// @notice add or remove users from allowList
function setAllowList(address[] memory user, bool[] memory val) external;
/// @notice enable or disable allowList
function setAllowListEnabled(bool _allowListEnabled) external;
/// @notice check if user is in allowList
function isAllowed(address user) external view returns (bool);
/// @notice check if allowList is enabled
function allowListEnabled() external view returns (bool);
function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox) external;
/// @notice returns the current admin
function getProxyAdmin() external view returns (address);
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.4.21 <0.9.0;
interface IOwnable {
function owner() external view returns (address);
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
pragma experimental ABIEncoderV2;
import "../libraries/IGasRefunder.sol";
import "./IDelayedMessageProvider.sol";
import "./IBridge.sol";
interface ISequencerInbox is IDelayedMessageProvider {
struct MaxTimeVariation {
uint256 delayBlocks;
uint256 futureBlocks;
uint256 delaySeconds;
uint256 futureSeconds;
}
event SequencerBatchDelivered(
uint256 indexed batchSequenceNumber,
bytes32 indexed beforeAcc,
bytes32 indexed afterAcc,
bytes32 delayedAcc,
uint256 afterDelayedMessagesRead,
IBridge.TimeBounds timeBounds,
IBridge.BatchDataLocation dataLocation
);
event OwnerFunctionCalled(uint256 indexed id);
/// @dev a separate event that emits batch data when this isn't easily accessible in the tx.input
event SequencerBatchData(uint256 indexed batchSequenceNumber, bytes data);
/// @dev a valid keyset was added
event SetValidKeyset(bytes32 indexed keysetHash, bytes keysetBytes);
/// @dev a keyset was invalidated
event InvalidateKeyset(bytes32 indexed keysetHash);
function totalDelayedMessagesRead() external view returns (uint256);
function bridge() external view returns (IBridge);
/// @dev The size of the batch header
// solhint-disable-next-line func-name-mixedcase
function HEADER_LENGTH() external view returns (uint256);
/// @dev If the first batch data byte after the header has this bit set,
/// the sequencer inbox has authenticated the data. Currently only used for 4844 blob support.
/// See: https://github.com/OffchainLabs/nitro/blob/69de0603abf6f900a4128cab7933df60cad54ded/arbstate/das_reader.go
// solhint-disable-next-line func-name-mixedcase
function DATA_AUTHENTICATED_FLAG() external view returns (bytes1);
/// @dev If the first data byte after the header has this bit set,
/// then the batch data is to be found in 4844 data blobs
/// See: https://github.com/OffchainLabs/nitro/blob/69de0603abf6f900a4128cab7933df60cad54ded/arbstate/das_reader.go
// solhint-disable-next-line func-name-mixedcase
function DATA_BLOB_HEADER_FLAG() external view returns (bytes1);
/// @dev If the first data byte after the header has this bit set,
/// then the batch data is a das message
/// See: https://github.com/OffchainLabs/nitro/blob/69de0603abf6f900a4128cab7933df60cad54ded/arbstate/das_reader.go
// solhint-disable-next-line func-name-mixedcase
function DAS_MESSAGE_HEADER_FLAG() external view returns (bytes1);
/// @dev If the first data byte after the header has this bit set,
/// then the batch data is a das message that employs a merklesization strategy
/// See: https://github.com/OffchainLabs/nitro/blob/69de0603abf6f900a4128cab7933df60cad54ded/arbstate/das_reader.go
// solhint-disable-next-line func-name-mixedcase
function TREE_DAS_MESSAGE_HEADER_FLAG() external view returns (bytes1);
/// @dev If the first data byte after the header has this bit set,
/// then the batch data has been brotli compressed
/// See: https://github.com/OffchainLabs/nitro/blob/69de0603abf6f900a4128cab7933df60cad54ded/arbstate/das_reader.go
// solhint-disable-next-line func-name-mixedcase
function BROTLI_MESSAGE_HEADER_FLAG() external view returns (bytes1);
/// @dev If the first data byte after the header has this bit set,
/// then the batch data uses a zero heavy encoding
/// See: https://github.com/OffchainLabs/nitro/blob/69de0603abf6f900a4128cab7933df60cad54ded/arbstate/das_reader.go
// solhint-disable-next-line func-name-mixedcase
function ZERO_HEAVY_MESSAGE_HEADER_FLAG() external view returns (bytes1);
function rollup() external view returns (IOwnable);
function isBatchPoster(address) external view returns (bool);
function isSequencer(address) external view returns (bool);
function maxDataSize() external view returns (uint256);
/// @notice The batch poster manager has the ability to change the batch poster addresses
/// This enables the batch poster to do key rotation
function batchPosterManager() external view returns (address);
struct DasKeySetInfo {
bool isValidKeyset;
uint64 creationBlock;
}
/// @dev returns 4 uint256 to be compatible with older version
function maxTimeVariation()
external
view
returns (
uint256 delayBlocks,
uint256 futureBlocks,
uint256 delaySeconds,
uint256 futureSeconds
);
function dasKeySetInfo(bytes32) external view returns (bool, uint64);
/// @notice Remove force inclusion delay after a L1 chainId fork
function removeDelayAfterFork() external;
/// @notice Force messages from the delayed inbox to be included in the chain
/// Callable by any address, but message can only be force-included after maxTimeVariation.delayBlocks and
/// maxTimeVariation.delaySeconds has elapsed. As part of normal behaviour the sequencer will include these
/// messages so it's only necessary to call this if the sequencer is down, or not including any delayed messages.
/// @param _totalDelayedMessagesRead The total number of messages to read up to
/// @param kind The kind of the last message to be included
/// @param l1BlockAndTime The l1 block and the l1 timestamp of the last message to be included
/// @param baseFeeL1 The l1 gas price of the last message to be included
/// @param sender The sender of the last message to be included
/// @param messageDataHash The messageDataHash of the last message to be included
function forceInclusion(
uint256 _totalDelayedMessagesRead,
uint8 kind,
uint64[2] calldata l1BlockAndTime,
uint256 baseFeeL1,
address sender,
bytes32 messageDataHash
) external;
function inboxAccs(uint256 index) external view returns (bytes32);
function batchCount() external view returns (uint256);
function isValidKeysetHash(bytes32 ksHash) external view returns (bool);
/// @notice the creation block is intended to still be available after a keyset is deleted
function getKeysetCreationBlock(bytes32 ksHash) external view returns (uint256);
// ---------- BatchPoster functions ----------
function addSequencerL2BatchFromOrigin(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder
) external;
function addSequencerL2BatchFromOrigin(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder,
uint256 prevMessageCount,
uint256 newMessageCount
) external;
function addSequencerL2Batch(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder,
uint256 prevMessageCount,
uint256 newMessageCount
) external;
function addSequencerL2BatchFromBlobs(
uint256 sequenceNumber,
uint256 afterDelayedMessagesRead,
IGasRefunder gasRefunder,
uint256 prevMessageCount,
uint256 newMessageCount
) external;
// ---------- onlyRollupOrOwner functions ----------
/**
* @notice Set max delay for sequencer inbox
* @param maxTimeVariation_ the maximum time variation parameters
*/
function setMaxTimeVariation(MaxTimeVariation memory maxTimeVariation_) external;
/**
* @notice Updates whether an address is authorized to be a batch poster at the sequencer inbox
* @param addr the address
* @param isBatchPoster_ if the specified address should be authorized as a batch poster
*/
function setIsBatchPoster(address addr, bool isBatchPoster_) external;
/**
* @notice Makes Data Availability Service keyset valid
* @param keysetBytes bytes of the serialized keyset
*/
function setValidKeyset(bytes calldata keysetBytes) external;
/**
* @notice Invalidates a Data Availability Service keyset
* @param ksHash hash of the keyset
*/
function invalidateKeysetHash(bytes32 ksHash) external;
/**
* @notice Updates whether an address is authorized to be a sequencer.
* @dev The IsSequencer information is used only off-chain by the nitro node to validate sequencer feed signer.
* @param addr the address
* @param isSequencer_ if the specified address should be authorized as a sequencer
*/
function setIsSequencer(address addr, bool isSequencer_) external;
/**
* @notice Updates the batch poster manager, the address which has the ability to rotate batch poster keys
* @param newBatchPosterManager The new batch poster manager to be set
*/
function setBatchPosterManager(address newBatchPosterManager) external;
/// @notice Allows the rollup owner to sync the rollup address
function updateRollupAddress() external;
// ---------- initializer ----------
function initialize(IBridge bridge_, MaxTimeVariation calldata maxTimeVariation_) external;
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
library AddressAliasHelper {
uint160 internal 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) {
unchecked {
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) {
unchecked {
l1Address = address(uint160(l2Address) - OFFSET);
}
}
}// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.4; uint64 constant NO_CHAL_INDEX = 0; // Expected seconds per block in Ethereum PoS uint256 constant ETH_POS_BLOCK_TIME = 12; /// @dev If nativeTokenDecimals is different than 18 decimals, bridge will inflate or deflate token amounts /// when depositing to child chain to match 18 decimal denomination. Opposite process happens when /// amount is withdrawn back to parent chain. In order to avoid uint256 overflows we restrict max number /// of decimals to 36 which should be enough for most practical use-cases. uint8 constant MAX_ALLOWED_NATIVE_TOKEN_DECIMALS = uint8(36); /// @dev Max amount of erc20 native token that can deposit when upscaling is required (i.e. < 18 decimals) /// Amounts higher than this would risk uint256 overflows when adjusting decimals. Considering /// 18 decimals are 60 bits, we choose 2^192 as the limit which equals to ~6.3*10^57 weis of token uint256 constant MAX_UPSCALE_AMOUNT = type(uint192).max;
// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
library DecimalsConverterHelper {
/// @notice generic function for mapping amount from one decimal denomination to another
/// @dev Ie. let's say amount is 752. If token has 16 decimals and is being adjusted to
/// 18 decimals then amount will be 75200. If token has 20 decimals adjusted amount
/// is 7. If token uses no decimals converted amount is 752*10^18.
/// When amount is adjusted from 18 decimals back to native token decimals, opposite
/// process is performed.
/// @param amount amount to convert
/// @param decimalsIn current decimals
/// @param decimalsOut target decimals
/// @return amount converted to 'decimalsOut' decimals
function adjustDecimals(
uint256 amount,
uint8 decimalsIn,
uint8 decimalsOut
) internal pure returns (uint256) {
if (decimalsIn == decimalsOut) {
return amount;
} else if (decimalsIn < decimalsOut) {
return amount * 10**(decimalsOut - decimalsIn);
} else {
return amount / 10**(decimalsIn - decimalsOut);
}
}
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import {NotOwner} from "./Error.sol";
/// @dev A stateless contract that allows you to infer if the current call has been delegated or not
/// Pattern used here is from UUPS implementation by the OpenZeppelin team
abstract contract DelegateCallAware {
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegate call. This allows a function to be
* callable on the proxy contract but not on the logic contract.
*/
modifier onlyDelegated() {
require(address(this) != __self, "Function must be called through delegatecall");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "Function must not be called through delegatecall");
_;
}
/// @dev Check that msg.sender is the current EIP 1967 proxy admin
modifier onlyProxyOwner() {
// Storage slot with the admin of the proxy contract
// This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1
bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
address admin;
assembly {
admin := sload(slot)
}
if (msg.sender != admin) revert NotOwner(msg.sender, admin);
_;
}
}// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.4;
/// @dev Init was already called
error AlreadyInit();
/// @dev Init was called with param set to zero that must be nonzero
error HadZeroInit();
/// @dev Thrown when post upgrade init validation fails
error BadPostUpgradeInit();
/// @dev Thrown when non owner tries to access an only-owner function
/// @param sender The msg.sender who is not the owner
/// @param owner The owner address
error NotOwner(address sender, address owner);
/// @dev Thrown when an address that is not the rollup tries to call an only-rollup function
/// @param sender The sender who is not the rollup
/// @param rollup The rollup address authorized to call this function
error NotRollup(address sender, address rollup);
/// @dev Thrown when the contract was not called directly from the origin ie msg.sender != tx.origin
error NotOrigin();
/// @dev Provided data was too large
/// @param dataLength The length of the data that is too large
/// @param maxDataLength The max length the data can be
error DataTooLarge(uint256 dataLength, uint256 maxDataLength);
/// @dev The provided is not a contract and was expected to be
/// @param addr The adddress in question
error NotContract(address addr);
/// @dev The merkle proof provided was too long
/// @param actualLength The length of the merkle proof provided
/// @param maxProofLength The max length a merkle proof can have
error MerkleProofTooLong(uint256 actualLength, uint256 maxProofLength);
/// @dev Thrown when an un-authorized address tries to access an admin function
/// @param sender The un-authorized sender
/// @param rollup The rollup, which would be authorized
/// @param owner The rollup's owner, which would be authorized
error NotRollupOrOwner(address sender, address rollup, address owner);
// Bridge Errors
/// @dev Thrown when an un-authorized address tries to access an only-inbox function
/// @param sender The un-authorized sender
error NotDelayedInbox(address sender);
/// @dev Thrown when an un-authorized address tries to access an only-sequencer-inbox function
/// @param sender The un-authorized sender
error NotSequencerInbox(address sender);
/// @dev Thrown when an un-authorized address tries to access an only-outbox function
/// @param sender The un-authorized sender
error NotOutbox(address sender);
/// @dev the provided outbox address isn't valid
/// @param outbox address of outbox being set
error InvalidOutboxSet(address outbox);
/// @dev The provided token address isn't valid
/// @param token address of token being set
error InvalidTokenSet(address token);
/// @dev Call to this specific address is not allowed
/// @param target address of the call receiver
error CallTargetNotAllowed(address target);
/// @dev Call that changes the balance of ERC20Bridge is not allowed
error CallNotAllowed();
// Inbox Errors
/// @dev msg.value sent to the inbox isn't high enough
error InsufficientValue(uint256 expected, uint256 actual);
/// @dev submission cost provided isn't enough to create retryable ticket
error InsufficientSubmissionCost(uint256 expected, uint256 actual);
/// @dev address not allowed to interact with the given contract
error NotAllowedOrigin(address origin);
/// @dev used to convey retryable tx data in eth calls without requiring a tx trace
/// this follows a pattern similar to EIP-3668 where reverts surface call information
error RetryableData(
address from,
address to,
uint256 l2CallValue,
uint256 deposit,
uint256 maxSubmissionCost,
address excessFeeRefundAddress,
address callValueRefundAddress,
uint256 gasLimit,
uint256 maxFeePerGas,
bytes data
);
/// @dev Thrown when a L1 chainId fork is detected
error L1Forked();
/// @dev Thrown when a L1 chainId fork is not detected
error NotForked();
/// @dev The provided gasLimit is larger than uint64
error GasLimitTooLarge();
/// @dev The provided amount cannot be adjusted to 18 decimals due to overflow
error AmountTooLarge(uint256 amount);
/// @dev Number of native token's decimals is restricted to enable conversions to 18 decimals
error NativeTokenDecimalsTooLarge(uint256 decimals);
// Outbox Errors
/// @dev The provided proof was too long
/// @param proofLength The length of the too-long proof
error ProofTooLong(uint256 proofLength);
/// @dev The output index was greater than the maximum
/// @param index The output index
/// @param maxIndex The max the index could be
error PathNotMinimal(uint256 index, uint256 maxIndex);
/// @dev The calculated root does not exist
/// @param root The calculated root
error UnknownRoot(bytes32 root);
/// @dev The record has already been spent
/// @param index The index of the spent record
error AlreadySpent(uint256 index);
/// @dev A call to the bridge failed with no return data
error BridgeCallFailed();
// Sequencer Inbox Errors
/// @dev Thrown when someone attempts to read fewer messages than have already been read
error DelayedBackwards();
/// @dev Thrown when someone attempts to read more messages than exist
error DelayedTooFar();
/// @dev Force include can only read messages more blocks old than the delay period
error ForceIncludeBlockTooSoon();
/// @dev Force include can only read messages more seconds old than the delay period
error ForceIncludeTimeTooSoon();
/// @dev The message provided did not match the hash in the delayed inbox
error IncorrectMessagePreimage();
/// @dev This can only be called by the batch poster
error NotBatchPoster();
/// @dev The sequence number provided to this message was inconsistent with the number of batches already included
error BadSequencerNumber(uint256 stored, uint256 received);
/// @dev The sequence message number provided to this message was inconsistent with the previous one
error BadSequencerMessageNumber(uint256 stored, uint256 received);
/// @dev Tried to create an already valid Data Availability Service keyset
error AlreadyValidDASKeyset(bytes32);
/// @dev Tried to use or invalidate an already invalid Data Availability Service keyset
error NoSuchKeyset(bytes32);
/// @dev Thrown when the provided address is not the designated batch poster manager
error NotBatchPosterManager(address);
/// @dev Thrown when a data blob feature is attempted to be used on a chain that doesnt support it
error DataBlobsNotSupported();
/// @dev Thrown when an init param was supplied as empty
error InitParamZero(string name);
/// @dev Thrown when data hashes where expected but not where present on the tx
error MissingDataHashes();
/// @dev Thrown when rollup is not updated with updateRollupAddress
error RollupNotChanged();
/// @dev Unsupported header flag was provided
error InvalidHeaderFlag(bytes1);
/// @dev SequencerInbox and Bridge are not in the same feeToken/ETH mode
error NativeTokenMismatch();
/// @dev Thrown when a deprecated function is called
error Deprecated();
/// @dev Thrown when any component of maxTimeVariation is over uint64
error BadMaxTimeVariation();// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE
// SPDX-License-Identifier: BUSL-1.1
// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;
interface IGasRefunder {
function onGasSpent(
address payable spender,
uint256 gasUsed,
uint256 calldataSize
) external returns (bool success);
}// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.4; uint8 constant L2_MSG = 3; uint8 constant L1MessageType_L2FundedByL1 = 7; uint8 constant L1MessageType_submitRetryableTx = 9; uint8 constant L1MessageType_ethDeposit = 12; uint8 constant L1MessageType_batchPostingReport = 13; uint8 constant L2MessageType_unsignedEOATx = 0; uint8 constant L2MessageType_unsignedContractTx = 1; uint8 constant ROLLUP_PROTOCOL_EVENT_TYPE = 8; uint8 constant INITIALIZATION_MSG_TYPE = 11;
{
"optimizer": {
"enabled": true,
"runs": 100
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract ABI
API[{"inputs":[],"name":"ERC1820_DEPLOYER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC1820_PAYLOAD","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC1820_VALUE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC2470_DEPLOYER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC2470_PAYLOAD","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC2470_VALUE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NICK_CREATE2_DEPLOYER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NICK_CREATE2_PAYLOAD","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NICK_CREATE2_VALUE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZOLTU_CREATE2_DEPLOYER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZOLTU_CREATE2_PAYLOAD","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZOLTU_VALUE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IInboxBase","name":"inbox","type":"address"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"}],"name":"getDeploymentTotalCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_inbox","type":"address"},{"internalType":"address","name":"_nativeToken","type":"address"},{"internalType":"uint256","name":"_maxFeePerGas","type":"uint256"}],"name":"perform","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506118c3806100206000396000f3fe6080604052600436106100bd5760003560e01c80639ed2c6f01161006f5780639ed2c6f0146101bd578063acd7d02a146101d8578063d3a3faab146101f8578063d7c641e714610220578063db633c3e14610235578063dd0c625a14610142578063ef77e71a1461025157600080fd5b80631b9a680c146100c2578063290302ce146100ed5780632e7966411461012d5780634367d6521461014257806355e34a6b1461016b57806375ae22b51461019357806389cf8ae6146101a8575b600080fd5b3480156100ce57600080fd5b506100d7610279565b6040516100e491906108fb565b60405180910390f35b3480156100f957600080fd5b5061011573a990077c3205cbdf861e17fa532eeb069ce9ff9681565b6040516001600160a01b0390911681526020016100e4565b34801561013957600080fd5b506100d7610295565b34801561014e57600080fd5b5061015d662386f26fc1000081565b6040519081526020016100e4565b34801561017757600080fd5b5061011573bb6e024b9cffacb947a71991e386681b1cd1477d81565b34801561019f57600080fd5b506100d76102b4565b3480156101b457600080fd5b506100d76102d0565b3480156101c957600080fd5b5061015d6657c084e5f3c00081565b3480156101e457600080fd5b5061015d6101f3366004610968565b6102ef565b34801561020457600080fd5b50610115734c8d290a1b368ac4728d83a9e8321fc3af2b39b181565b61023361022e366004610994565b6103df565b005b34801561024157600080fd5b5061015d67011c37937e08000081565b34801561025d57600080fd5b50610115733fab184622dc19b6109349b94811493bf2a4536281565b6040518060e0016040528060a881526020016117e660a8913981565b60405180610a600160405280610a3c8152602001610bb9610a3c913981565b6040518060c00160405280608181526020016115f56081913981565b604051806101a001604052806101708152602001611676610170913981565b60405163a66b327d60e01b81526000600482018190524860248301529081906001600160a01b0385169063a66b327d9060440160206040518083038186803b15801561033a57600080fd5b505afa15801561034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037291906109d5565b905061038083615208610a04565b61038a9082610a23565b610395906004610a04565b67011c37937e080000662386f26fc100006103b76657c084e5f3c00082610a23565b6103c19190610a23565b6103cb9190610a23565b6103d59190610a23565b9150505b92915050565b61042083662386f26fc10000733fab184622dc19b6109349b94811493bf2a453626040518060e0016040528060a881526020016117e660a89139868661052b565b610464836657c084e5f3c00073bb6e024b9cffacb947a71991e386681b1cd1477d604051806101a0016040528061017081526020016116766101709139868661052b565b6104a583662386f26fc10000734c8d290a1b368ac4728d83a9e8321fc3af2b39b16040518060c00160405280608181526020016115f560819139868661052b565b6104ea8367011c37937e08000073a990077c3205cbdf861e17fa532eeb069ce9ff9660405180610a600160405280610a3c8152602001610bb9610a3c9139868661052b565b6001600160a01b0382166105265760405133904780156108fc02916000818181858888f19350505050158015610524573d6000803e3d6000fd5b505b505050565b60405163a66b327d60e01b8152600060048201819052486024830152906001600160a01b0388169063a66b327d9060440160206040518083038186803b15801561057457600080fd5b505afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac91906109d5565b905060006105bc83615208610a04565b6105c68389610a23565b6105d09190610a23565b90506001600160a01b038416156107b85760008190506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561062157600080fd5b505afa158015610635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106599190610a3b565b905060128160ff1610156106c357610672816012610a65565b61067d90600a610b6c565b6106879084610b7b565b915082610695826012610a65565b6106a090600a610b6c565b6106aa9084610a04565b10156106be57816106ba81610b9d565b9250505b6106f2565b60128160ff1611156106f2576106da601282610a65565b6106e590600a610b6c565b6106ef9084610a04565b91505b604051632a4f421360e11b81526001600160a01b038981166004830152602482018b9052604482018690523360648301819052608483015261520860a483015260c4820187905260e4820184905261012061010483015260006101248301528b169063549e84269061014401602060405180830381600087803b15801561077857600080fd5b505af115801561078c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b091906109d5565b505050610872565b60405163679b6ded60e01b81526001600160a01b03878116600483015260248201899052604482018490523360648301819052608483015261520860a483015260c4820185905261010060e4830152600061010483015289169063679b6ded908390610124016020604051808303818588803b15801561083757600080fd5b505af115801561084b573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061087091906109d5565b505b60405163b75436bb60e01b81526001600160a01b0389169063b75436bb9061089e9088906004016108fb565b602060405180830381600087803b1580156108b857600080fd5b505af11580156108cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f091906109d5565b505050505050505050565b600060208083528351808285015260005b818110156109285785810183015185820160400152820161090c565b8181111561093a576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b038116811461096557600080fd5b50565b6000806040838503121561097b57600080fd5b823561098681610950565b946020939093013593505050565b6000806000606084860312156109a957600080fd5b83356109b481610950565b925060208401356109c481610950565b929592945050506040919091013590565b6000602082840312156109e757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610a1e57610a1e6109ee565b500290565b60008219821115610a3657610a366109ee565b500190565b600060208284031215610a4d57600080fd5b815160ff81168114610a5e57600080fd5b9392505050565b600060ff821660ff841680821015610a7f57610a7f6109ee565b90039392505050565b600181815b80851115610ac3578160001904821115610aa957610aa96109ee565b80851615610ab657918102915b93841c9390800290610a8d565b509250929050565b600082610ada575060016103d9565b81610ae7575060006103d9565b8160018114610afd5760028114610b0757610b23565b60019150506103d9565b60ff841115610b1857610b186109ee565b50506001821b6103d9565b5060208310610133831016604e8410600b8410161715610b46575081810a6103d9565b610b508383610a88565b8060001904821115610b6457610b646109ee565b029392505050565b6000610a5e60ff841683610acb565b600082610b9857634e487b7160e01b600052601260045260246000fd5b500490565b6000600019821415610bb157610bb16109ee565b506001019056fe04f90a388085174876e800830c35008080b909e5608060405234801561001057600080fd5b506109c5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063a41e7d5111610078578063a41e7d51146101d4578063aabbb8ca1461020a578063b705676514610236578063f712f3e814610280576100a5565b806329965a1d146100aa5780633d584063146100e25780635df8122f1461012457806365ba36c114610152575b600080fd5b6100e0600480360360608110156100c057600080fd5b50600160a060020a038135811691602081013591604090910135166102b6565b005b610108600480360360208110156100f857600080fd5b5035600160a060020a0316610570565b60408051600160a060020a039092168252519081900360200190f35b6100e06004803603604081101561013a57600080fd5b50600160a060020a03813581169160200135166105bc565b6101c26004803603602081101561016857600080fd5b81019060208101813564010000000081111561018357600080fd5b82018360208201111561019557600080fd5b803590602001918460018302840111640100000000831117156101b757600080fd5b5090925090506106b3565b60408051918252519081900360200190f35b6100e0600480360360408110156101ea57600080fd5b508035600160a060020a03169060200135600160e060020a0319166106ee565b6101086004803603604081101561022057600080fd5b50600160a060020a038135169060200135610778565b61026c6004803603604081101561024c57600080fd5b508035600160a060020a03169060200135600160e060020a0319166107ef565b604080519115158252519081900360200190f35b61026c6004803603604081101561029657600080fd5b508035600160a060020a03169060200135600160e060020a0319166108aa565b6000600160a060020a038416156102cd57836102cf565b335b9050336102db82610570565b600160a060020a031614610339576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b6103428361092a565b15610397576040805160e560020a62461bcd02815260206004820152601a60248201527f4d757374206e6f7420626520616e204552433136352068617368000000000000604482015290519081900360640190fd5b600160a060020a038216158015906103b85750600160a060020a0382163314155b156104ff5760405160200180807f455243313832305f4143434550545f4d4147494300000000000000000000000081525060140190506040516020818303038152906040528051906020012082600160a060020a031663249cb3fa85846040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083815260200182600160a060020a0316600160a060020a031681526020019250505060206040518083038186803b15801561047e57600080fd5b505afa158015610492573d6000803e3d6000fd5b505050506040513d60208110156104a857600080fd5b5051146104ff576040805160e560020a62461bcd02815260206004820181905260248201527f446f6573206e6f7420696d706c656d656e742074686520696e74657266616365604482015290519081900360640190fd5b600160a060020a03818116600081815260208181526040808320888452909152808220805473ffffffffffffffffffffffffffffffffffffffff19169487169485179055518692917f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db15391a450505050565b600160a060020a03818116600090815260016020526040812054909116151561059a5750806105b7565b50600160a060020a03808216600090815260016020526040902054165b919050565b336105c683610570565b600160a060020a031614610624576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b81600160a060020a031681600160a060020a0316146106435780610646565b60005b600160a060020a03838116600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169585169590951790945592519184169290917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43509190a35050565b600082826040516020018083838082843780830192505050925050506040516020818303038152906040528051906020012090505b92915050565b6106f882826107ef565b610703576000610705565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b600080600160a060020a038416156107905783610792565b335b905061079d8361092a565b156107c357826107ad82826108aa565b6107b85760006107ba565b815b925050506106e8565b600160a060020a0390811660009081526020818152604080832086845290915290205416905092915050565b6000808061081d857f01ffc9a70000000000000000000000000000000000000000000000000000000061094c565b909250905081158061082d575080155b1561083d576000925050506106e8565b61084f85600160e060020a031961094c565b909250905081158061086057508015155b15610870576000925050506106e8565b61087a858561094c565b909250905060018214801561088f5750806001145b1561089f576001925050506106e8565b506000949350505050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff1615156108f2576108eb83836107ef565b90506106e8565b50600160a060020a03808316600081815260208181526040808320600160e060020a0319871684529091529020549091161492915050565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6040517f01ffc9a7000000000000000000000000000000000000000000000000000000008082526004820183905260009182919060208160248189617530fa90519096909550935050505056fea165627a7a72305820377f4a2d4301ede9949f163f319021a6e9c687c292a5e2b2c4734c126b524e6c00291ba01820182018201820182018201820182018201820182018201820182018201820a0182018201820182018201820182018201820182018201820182018201820182004f87e8085174876e800830186a08080ad601f80600e600039806000f350fe60003681823780368234f58015156014578182fd5b80825250506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a0222222222222222222222222222222222222222222222222222222222222222204f9016c8085174876e8008303c4d88080b90154608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c634300060200331b8324700082247004f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222a2646970667358221220187c08699d14cfac8f6e3b05fa2f4836377caed15f7dcfadae148f78a75969c964736f6c63430008090033
Deployed Bytecode
0x6080604052600436106100bd5760003560e01c80639ed2c6f01161006f5780639ed2c6f0146101bd578063acd7d02a146101d8578063d3a3faab146101f8578063d7c641e714610220578063db633c3e14610235578063dd0c625a14610142578063ef77e71a1461025157600080fd5b80631b9a680c146100c2578063290302ce146100ed5780632e7966411461012d5780634367d6521461014257806355e34a6b1461016b57806375ae22b51461019357806389cf8ae6146101a8575b600080fd5b3480156100ce57600080fd5b506100d7610279565b6040516100e491906108fb565b60405180910390f35b3480156100f957600080fd5b5061011573a990077c3205cbdf861e17fa532eeb069ce9ff9681565b6040516001600160a01b0390911681526020016100e4565b34801561013957600080fd5b506100d7610295565b34801561014e57600080fd5b5061015d662386f26fc1000081565b6040519081526020016100e4565b34801561017757600080fd5b5061011573bb6e024b9cffacb947a71991e386681b1cd1477d81565b34801561019f57600080fd5b506100d76102b4565b3480156101b457600080fd5b506100d76102d0565b3480156101c957600080fd5b5061015d6657c084e5f3c00081565b3480156101e457600080fd5b5061015d6101f3366004610968565b6102ef565b34801561020457600080fd5b50610115734c8d290a1b368ac4728d83a9e8321fc3af2b39b181565b61023361022e366004610994565b6103df565b005b34801561024157600080fd5b5061015d67011c37937e08000081565b34801561025d57600080fd5b50610115733fab184622dc19b6109349b94811493bf2a4536281565b6040518060e0016040528060a881526020016117e660a8913981565b60405180610a600160405280610a3c8152602001610bb9610a3c913981565b6040518060c00160405280608181526020016115f56081913981565b604051806101a001604052806101708152602001611676610170913981565b60405163a66b327d60e01b81526000600482018190524860248301529081906001600160a01b0385169063a66b327d9060440160206040518083038186803b15801561033a57600080fd5b505afa15801561034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037291906109d5565b905061038083615208610a04565b61038a9082610a23565b610395906004610a04565b67011c37937e080000662386f26fc100006103b76657c084e5f3c00082610a23565b6103c19190610a23565b6103cb9190610a23565b6103d59190610a23565b9150505b92915050565b61042083662386f26fc10000733fab184622dc19b6109349b94811493bf2a453626040518060e0016040528060a881526020016117e660a89139868661052b565b610464836657c084e5f3c00073bb6e024b9cffacb947a71991e386681b1cd1477d604051806101a0016040528061017081526020016116766101709139868661052b565b6104a583662386f26fc10000734c8d290a1b368ac4728d83a9e8321fc3af2b39b16040518060c00160405280608181526020016115f560819139868661052b565b6104ea8367011c37937e08000073a990077c3205cbdf861e17fa532eeb069ce9ff9660405180610a600160405280610a3c8152602001610bb9610a3c9139868661052b565b6001600160a01b0382166105265760405133904780156108fc02916000818181858888f19350505050158015610524573d6000803e3d6000fd5b505b505050565b60405163a66b327d60e01b8152600060048201819052486024830152906001600160a01b0388169063a66b327d9060440160206040518083038186803b15801561057457600080fd5b505afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac91906109d5565b905060006105bc83615208610a04565b6105c68389610a23565b6105d09190610a23565b90506001600160a01b038416156107b85760008190506000856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561062157600080fd5b505afa158015610635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106599190610a3b565b905060128160ff1610156106c357610672816012610a65565b61067d90600a610b6c565b6106879084610b7b565b915082610695826012610a65565b6106a090600a610b6c565b6106aa9084610a04565b10156106be57816106ba81610b9d565b9250505b6106f2565b60128160ff1611156106f2576106da601282610a65565b6106e590600a610b6c565b6106ef9084610a04565b91505b604051632a4f421360e11b81526001600160a01b038981166004830152602482018b9052604482018690523360648301819052608483015261520860a483015260c4820187905260e4820184905261012061010483015260006101248301528b169063549e84269061014401602060405180830381600087803b15801561077857600080fd5b505af115801561078c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b091906109d5565b505050610872565b60405163679b6ded60e01b81526001600160a01b03878116600483015260248201899052604482018490523360648301819052608483015261520860a483015260c4820185905261010060e4830152600061010483015289169063679b6ded908390610124016020604051808303818588803b15801561083757600080fd5b505af115801561084b573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061087091906109d5565b505b60405163b75436bb60e01b81526001600160a01b0389169063b75436bb9061089e9088906004016108fb565b602060405180830381600087803b1580156108b857600080fd5b505af11580156108cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f091906109d5565b505050505050505050565b600060208083528351808285015260005b818110156109285785810183015185820160400152820161090c565b8181111561093a576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b038116811461096557600080fd5b50565b6000806040838503121561097b57600080fd5b823561098681610950565b946020939093013593505050565b6000806000606084860312156109a957600080fd5b83356109b481610950565b925060208401356109c481610950565b929592945050506040919091013590565b6000602082840312156109e757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610a1e57610a1e6109ee565b500290565b60008219821115610a3657610a366109ee565b500190565b600060208284031215610a4d57600080fd5b815160ff81168114610a5e57600080fd5b9392505050565b600060ff821660ff841680821015610a7f57610a7f6109ee565b90039392505050565b600181815b80851115610ac3578160001904821115610aa957610aa96109ee565b80851615610ab657918102915b93841c9390800290610a8d565b509250929050565b600082610ada575060016103d9565b81610ae7575060006103d9565b8160018114610afd5760028114610b0757610b23565b60019150506103d9565b60ff841115610b1857610b186109ee565b50506001821b6103d9565b5060208310610133831016604e8410600b8410161715610b46575081810a6103d9565b610b508383610a88565b8060001904821115610b6457610b646109ee565b029392505050565b6000610a5e60ff841683610acb565b600082610b9857634e487b7160e01b600052601260045260246000fd5b500490565b6000600019821415610bb157610bb16109ee565b506001019056fe04f90a388085174876e800830c35008080b909e5608060405234801561001057600080fd5b506109c5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063a41e7d5111610078578063a41e7d51146101d4578063aabbb8ca1461020a578063b705676514610236578063f712f3e814610280576100a5565b806329965a1d146100aa5780633d584063146100e25780635df8122f1461012457806365ba36c114610152575b600080fd5b6100e0600480360360608110156100c057600080fd5b50600160a060020a038135811691602081013591604090910135166102b6565b005b610108600480360360208110156100f857600080fd5b5035600160a060020a0316610570565b60408051600160a060020a039092168252519081900360200190f35b6100e06004803603604081101561013a57600080fd5b50600160a060020a03813581169160200135166105bc565b6101c26004803603602081101561016857600080fd5b81019060208101813564010000000081111561018357600080fd5b82018360208201111561019557600080fd5b803590602001918460018302840111640100000000831117156101b757600080fd5b5090925090506106b3565b60408051918252519081900360200190f35b6100e0600480360360408110156101ea57600080fd5b508035600160a060020a03169060200135600160e060020a0319166106ee565b6101086004803603604081101561022057600080fd5b50600160a060020a038135169060200135610778565b61026c6004803603604081101561024c57600080fd5b508035600160a060020a03169060200135600160e060020a0319166107ef565b604080519115158252519081900360200190f35b61026c6004803603604081101561029657600080fd5b508035600160a060020a03169060200135600160e060020a0319166108aa565b6000600160a060020a038416156102cd57836102cf565b335b9050336102db82610570565b600160a060020a031614610339576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b6103428361092a565b15610397576040805160e560020a62461bcd02815260206004820152601a60248201527f4d757374206e6f7420626520616e204552433136352068617368000000000000604482015290519081900360640190fd5b600160a060020a038216158015906103b85750600160a060020a0382163314155b156104ff5760405160200180807f455243313832305f4143434550545f4d4147494300000000000000000000000081525060140190506040516020818303038152906040528051906020012082600160a060020a031663249cb3fa85846040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083815260200182600160a060020a0316600160a060020a031681526020019250505060206040518083038186803b15801561047e57600080fd5b505afa158015610492573d6000803e3d6000fd5b505050506040513d60208110156104a857600080fd5b5051146104ff576040805160e560020a62461bcd02815260206004820181905260248201527f446f6573206e6f7420696d706c656d656e742074686520696e74657266616365604482015290519081900360640190fd5b600160a060020a03818116600081815260208181526040808320888452909152808220805473ffffffffffffffffffffffffffffffffffffffff19169487169485179055518692917f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db15391a450505050565b600160a060020a03818116600090815260016020526040812054909116151561059a5750806105b7565b50600160a060020a03808216600090815260016020526040902054165b919050565b336105c683610570565b600160a060020a031614610624576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b81600160a060020a031681600160a060020a0316146106435780610646565b60005b600160a060020a03838116600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169585169590951790945592519184169290917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43509190a35050565b600082826040516020018083838082843780830192505050925050506040516020818303038152906040528051906020012090505b92915050565b6106f882826107ef565b610703576000610705565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b600080600160a060020a038416156107905783610792565b335b905061079d8361092a565b156107c357826107ad82826108aa565b6107b85760006107ba565b815b925050506106e8565b600160a060020a0390811660009081526020818152604080832086845290915290205416905092915050565b6000808061081d857f01ffc9a70000000000000000000000000000000000000000000000000000000061094c565b909250905081158061082d575080155b1561083d576000925050506106e8565b61084f85600160e060020a031961094c565b909250905081158061086057508015155b15610870576000925050506106e8565b61087a858561094c565b909250905060018214801561088f5750806001145b1561089f576001925050506106e8565b506000949350505050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff1615156108f2576108eb83836107ef565b90506106e8565b50600160a060020a03808316600081815260208181526040808320600160e060020a0319871684529091529020549091161492915050565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6040517f01ffc9a7000000000000000000000000000000000000000000000000000000008082526004820183905260009182919060208160248189617530fa90519096909550935050505056fea165627a7a72305820377f4a2d4301ede9949f163f319021a6e9c687c292a5e2b2c4734c126b524e6c00291ba01820182018201820182018201820182018201820182018201820182018201820a0182018201820182018201820182018201820182018201820182018201820182004f87e8085174876e800830186a08080ad601f80600e600039806000f350fe60003681823780368234f58015156014578182fd5b80825250506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a0222222222222222222222222222222222222222222222222222222222222222204f9016c8085174876e8008303c4d88080b90154608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c634300060200331b8324700082247004f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222a2646970667358221220187c08699d14cfac8f6e3b05fa2f4836377caed15f7dcfadae148f78a75969c964736f6c63430008090033
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.