Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 25 from a total of 1,178 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 24396554 | 23 days ago | IN | 0 ETH | 0.00001886 | ||||
| Withdraw | 24361144 | 28 days ago | IN | 0 ETH | 0.00000718 | ||||
| Withdraw | 23924222 | 89 days ago | IN | 0 ETH | 0.00024302 | ||||
| Withdraw | 22855989 | 239 days ago | IN | 0 ETH | 0.00028595 | ||||
| Unstake | 22625394 | 271 days ago | IN | 0 ETH | 0.00049658 | ||||
| Withdraw | 22598721 | 275 days ago | IN | 0 ETH | 0.00033456 | ||||
| Withdraw | 22598719 | 275 days ago | IN | 0 ETH | 0.00032515 | ||||
| Bond Transfer Ro... | 22598255 | 275 days ago | IN | 0 ETH | 0.00023462 | ||||
| Bond Transfer Ro... | 22598239 | 275 days ago | IN | 0 ETH | 0.00023823 | ||||
| Settle Bonded Wi... | 22590196 | 276 days ago | IN | 0 ETH | 0.00022462 | ||||
| Withdraw | 22590190 | 276 days ago | IN | 0 ETH | 0.00057271 | ||||
| Withdraw | 22590188 | 276 days ago | IN | 0 ETH | 0.00061075 | ||||
| Withdraw | 22590187 | 276 days ago | IN | 0 ETH | 0.00073892 | ||||
| Settle Bonded Wi... | 22590125 | 276 days ago | IN | 0 ETH | 0.00014724 | ||||
| Withdraw | 22586322 | 276 days ago | IN | 0 ETH | 0.00024717 | ||||
| Bond Transfer Ro... | 22584073 | 277 days ago | IN | 0 ETH | 0.0004012 | ||||
| Withdraw | 22583086 | 277 days ago | IN | 0 ETH | 0.00032814 | ||||
| Bond Transfer Ro... | 22582783 | 277 days ago | IN | 0 ETH | 0.00060741 | ||||
| Bond Transfer Ro... | 22536783 | 283 days ago | IN | 0 ETH | 0.00039497 | ||||
| Withdraw | 22514553 | 286 days ago | IN | 0 ETH | 0.00009906 | ||||
| Withdraw | 22502009 | 288 days ago | IN | 0 ETH | 0.00017729 | ||||
| Bond Transfer Ro... | 22501969 | 288 days ago | IN | 0 ETH | 0.0002108 | ||||
| Withdraw | 22447905 | 296 days ago | IN | 0 ETH | 0.00028877 | ||||
| Bond Transfer Ro... | 22445359 | 296 days ago | IN | 0 ETH | 0.00124982 | ||||
| Withdraw | 22337628 | 311 days ago | IN | 0 ETH | 0.00009274 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
L1_ERC20_Bridge
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 50000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "./L1_Bridge.sol";
/**
* @dev A L1_Bridge that uses an ERC20 as the canonical token
*/
contract L1_ERC20_Bridge is L1_Bridge {
using SafeERC20 for IERC20;
IERC20 public immutable l1CanonicalToken;
constructor (IERC20 _l1CanonicalToken, address[] memory bonders, address _governance) public L1_Bridge(bonders, _governance) {
l1CanonicalToken = _l1CanonicalToken;
}
/* ========== Override Functions ========== */
function _transferFromBridge(address recipient, uint256 amount) internal override {
l1CanonicalToken.safeTransfer(recipient, amount);
}
function _transferToBridge(address from, uint256 amount) internal override {
l1CanonicalToken.safeTransferFrom(from, address(this), amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.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 SafeMath for uint256;
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'
// solhint-disable-next-line max-line-length
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).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_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
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
/**
* @dev Accounting is an abstract contract that encapsulates the most critical logic in the Hop contracts.
* The accounting system works by using two balances that can only increase `_credit` and `_debit`.
* A bonder's available balance is the total credit minus the total debit. The contract exposes
* two external functions that allows a bonder to stake and unstake and exposes two internal
* functions to its child contracts that allow the child contract to add to the credit
* and debit balance. In addition, child contracts can override `_additionalDebit` to account
* for any additional debit balance in an alternative way. Lastly, it exposes a modifier,
* `requirePositiveBalance`, that can be used by child contracts to ensure the bonder does not
* use more than its available stake.
*/
abstract contract Accounting is ReentrancyGuard {
using SafeMath for uint256;
mapping(address => bool) private _isBonder;
mapping(address => uint256) private _credit;
mapping(address => uint256) private _debit;
event Stake (
address indexed account,
uint256 amount
);
event Unstake (
address indexed account,
uint256 amount
);
event BonderAdded (
address indexed newBonder
);
event BonderRemoved (
address indexed previousBonder
);
/* ========== Modifiers ========== */
modifier onlyBonder {
require(_isBonder[msg.sender], "ACT: Caller is not bonder");
_;
}
modifier onlyGovernance {
_requireIsGovernance();
_;
}
/// @dev Used by parent contract to ensure that the Bonder is solvent at the end of the transaction.
modifier requirePositiveBalance {
_;
require(getCredit(msg.sender) >= getDebitAndAdditionalDebit(msg.sender), "ACT: Not enough available credit");
}
/// @dev Sets the Bonder addresses
constructor(address[] memory bonders) public {
for (uint256 i = 0; i < bonders.length; i++) {
require(_isBonder[bonders[i]] == false, "ACT: Cannot add duplicate bonder");
_isBonder[bonders[i]] = true;
emit BonderAdded(bonders[i]);
}
}
/* ========== Virtual functions ========== */
/**
* @dev The following functions are overridden in L1_Bridge and L2_Bridge
*/
function _transferFromBridge(address recipient, uint256 amount) internal virtual;
function _transferToBridge(address from, uint256 amount) internal virtual;
function _requireIsGovernance() internal virtual;
/**
* @dev This function can be optionally overridden by a parent contract to track any additional
* debit balance in an alternative way.
*/
function _additionalDebit(address /*bonder*/) internal view virtual returns (uint256) {
this; // Silence state mutability warning without generating any additional byte code
return 0;
}
/* ========== Public/external getters ========== */
/**
* @dev Check if address is a Bonder
* @param maybeBonder The address being checked
* @return true if address is a Bonder
*/
function getIsBonder(address maybeBonder) public view returns (bool) {
return _isBonder[maybeBonder];
}
/**
* @dev Get the Bonder's credit balance
* @param bonder The owner of the credit balance being checked
* @return The credit balance for the Bonder
*/
function getCredit(address bonder) public view returns (uint256) {
return _credit[bonder];
}
/**
* @dev Gets the debit balance tracked by `_debit` and does not include `_additionalDebit()`
* @param bonder The owner of the debit balance being checked
* @return The debit amount for the Bonder
*/
function getRawDebit(address bonder) external view returns (uint256) {
return _debit[bonder];
}
/**
* @dev Get the Bonder's total debit
* @param bonder The owner of the debit balance being checked
* @return The Bonder's total debit balance
*/
function getDebitAndAdditionalDebit(address bonder) public view returns (uint256) {
return _debit[bonder].add(_additionalDebit(bonder));
}
/* ========== Bonder external functions ========== */
/**
* @dev Allows the Bonder to deposit tokens and increase its credit balance
* @param bonder The address being staked on
* @param amount The amount being staked
*/
function stake(address bonder, uint256 amount) external payable nonReentrant {
require(_isBonder[bonder] == true, "ACT: Address is not bonder");
_transferToBridge(msg.sender, amount);
_addCredit(bonder, amount);
emit Stake(bonder, amount);
}
/**
* @dev Allows the caller to withdraw any available balance and add to their debit balance
* @param amount The amount being unstaked
*/
function unstake(uint256 amount) external requirePositiveBalance nonReentrant {
_addDebit(msg.sender, amount);
_transferFromBridge(msg.sender, amount);
emit Unstake(msg.sender, amount);
}
/**
* @dev Add Bonder to allowlist
* @param bonder The address being added as a Bonder
*/
function addBonder(address bonder) external onlyGovernance {
require(_isBonder[bonder] == false, "ACT: Address is already bonder");
_isBonder[bonder] = true;
emit BonderAdded(bonder);
}
/**
* @dev Remove Bonder from allowlist
* @param bonder The address being removed as a Bonder
*/
function removeBonder(address bonder) external onlyGovernance {
require(_isBonder[bonder] == true, "ACT: Address is not bonder");
_isBonder[bonder] = false;
emit BonderRemoved(bonder);
}
/* ========== Internal functions ========== */
function _addCredit(address bonder, uint256 amount) internal {
_credit[bonder] = _credit[bonder].add(amount);
}
function _addDebit(address bonder, uint256 amount) internal {
_debit[bonder] = _debit[bonder].add(amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "./Accounting.sol";
import "../libraries/Lib_MerkleTree.sol";
/**
* @dev Bridge extends the accounting system and encapsulates the logic that is shared by both the
* L1 and L2 Bridges. It allows to TransferRoots to be set by parent contracts and for those
* TransferRoots to be withdrawn against. It also allows the bonder to bond and withdraw Transfers
* directly through `bondWithdrawal` and then settle those bonds against their TransferRoot once it
* has been set.
*/
abstract contract Bridge is Accounting {
using Lib_MerkleTree for bytes32;
struct TransferRoot {
uint256 total;
uint256 amountWithdrawn;
uint256 createdAt;
}
/* ========== Events ========== */
event Withdrew(
bytes32 indexed transferId,
address indexed recipient,
uint256 amount,
bytes32 transferNonce
);
event WithdrawalBonded(
bytes32 indexed transferId,
uint256 amount
);
event WithdrawalBondSettled(
address indexed bonder,
bytes32 indexed transferId,
bytes32 indexed rootHash
);
event MultipleWithdrawalsSettled(
address indexed bonder,
bytes32 indexed rootHash,
uint256 totalBondsSettled
);
event TransferRootSet(
bytes32 indexed rootHash,
uint256 totalAmount
);
/* ========== State ========== */
mapping(bytes32 => TransferRoot) private _transferRoots;
mapping(bytes32 => bool) private _spentTransferIds;
mapping(address => mapping(bytes32 => uint256)) private _bondedWithdrawalAmounts;
uint256 constant RESCUE_DELAY = 8 weeks;
constructor(address[] memory bonders) public Accounting(bonders) {}
/* ========== Public Getters ========== */
/**
* @dev Get the hash that represents an individual Transfer.
* @param chainId The id of the destination chain
* @param recipient The address receiving the Transfer
* @param amount The amount being transferred including the `_bonderFee`
* @param transferNonce Used to avoid transferId collisions
* @param bonderFee The amount paid to the address that withdraws the Transfer
* @param amountOutMin The minimum amount received after attempting to swap in the destination
* AMM market. 0 if no swap is intended.
* @param deadline The deadline for swapping in the destination AMM market. 0 if no
* swap is intended.
*/
function getTransferId(
uint256 chainId,
address recipient,
uint256 amount,
bytes32 transferNonce,
uint256 bonderFee,
uint256 amountOutMin,
uint256 deadline
)
public
pure
returns (bytes32)
{
return keccak256(abi.encode(
chainId,
recipient,
amount,
transferNonce,
bonderFee,
amountOutMin,
deadline
));
}
/**
* @notice getChainId can be overridden by subclasses if needed for compatibility or testing purposes.
* @dev Get the current chainId
* @return chainId The current chainId
*/
function getChainId() public virtual view returns (uint256 chainId) {
this; // Silence state mutability warning without generating any additional byte code
assembly {
chainId := chainid()
}
}
/**
* @dev Get the TransferRoot id for a given rootHash and totalAmount
* @param rootHash The Merkle root of the TransferRoot
* @param totalAmount The total of all Transfers in the TransferRoot
* @return The calculated transferRootId
*/
function getTransferRootId(bytes32 rootHash, uint256 totalAmount) public pure returns (bytes32) {
return keccak256(abi.encodePacked(rootHash, totalAmount));
}
/**
* @dev Get the TransferRoot for a given rootHash and totalAmount
* @param rootHash The Merkle root of the TransferRoot
* @param totalAmount The total of all Transfers in the TransferRoot
* @return The TransferRoot with the calculated transferRootId
*/
function getTransferRoot(bytes32 rootHash, uint256 totalAmount) public view returns (TransferRoot memory) {
return _transferRoots[getTransferRootId(rootHash, totalAmount)];
}
/**
* @dev Get the amount bonded for the withdrawal of a transfer
* @param bonder The Bonder of the withdrawal
* @param transferId The Transfer's unique identifier
* @return The amount bonded for a Transfer withdrawal
*/
function getBondedWithdrawalAmount(address bonder, bytes32 transferId) external view returns (uint256) {
return _bondedWithdrawalAmounts[bonder][transferId];
}
/**
* @dev Get the spent status of a transfer ID
* @param transferId The transfer's unique identifier
* @return True if the transferId has been spent
*/
function isTransferIdSpent(bytes32 transferId) external view returns (bool) {
return _spentTransferIds[transferId];
}
/* ========== User/Relayer External Functions ========== */
/**
* @notice Can be called by anyone (recipient or relayer)
* @dev Withdraw a Transfer from its destination bridge
* @param recipient The address receiving the Transfer
* @param amount The amount being transferred including the `_bonderFee`
* @param transferNonce Used to avoid transferId collisions
* @param bonderFee The amount paid to the address that withdraws the Transfer
* @param amountOutMin The minimum amount received after attempting to swap in the destination
* AMM market. 0 if no swap is intended. (only used to calculate `transferId` in this function)
* @param deadline The deadline for swapping in the destination AMM market. 0 if no
* swap is intended. (only used to calculate `transferId` in this function)
* @param rootHash The Merkle root of the TransferRoot
* @param transferRootTotalAmount The total amount being transferred in a TransferRoot
* @param transferIdTreeIndex The index of the transferId in the Merkle tree
* @param siblings The siblings of the transferId in the Merkle tree
* @param totalLeaves The total number of leaves in the Merkle tree
*/
function withdraw(
address recipient,
uint256 amount,
bytes32 transferNonce,
uint256 bonderFee,
uint256 amountOutMin,
uint256 deadline,
bytes32 rootHash,
uint256 transferRootTotalAmount,
uint256 transferIdTreeIndex,
bytes32[] calldata siblings,
uint256 totalLeaves
)
external
nonReentrant
{
bytes32 transferId = getTransferId(
getChainId(),
recipient,
amount,
transferNonce,
bonderFee,
amountOutMin,
deadline
);
require(
rootHash.verify(
transferId,
transferIdTreeIndex,
siblings,
totalLeaves
)
, "BRG: Invalid transfer proof");
bytes32 transferRootId = getTransferRootId(rootHash, transferRootTotalAmount);
_addToAmountWithdrawn(transferRootId, amount);
_fulfillWithdraw(transferId, recipient, amount, uint256(0));
emit Withdrew(transferId, recipient, amount, transferNonce);
}
/**
* @dev Allows the bonder to bond individual withdrawals before their TransferRoot has been committed.
* @param recipient The address receiving the Transfer
* @param amount The amount being transferred including the `_bonderFee`
* @param transferNonce Used to avoid transferId collisions
* @param bonderFee The amount paid to the address that withdraws the Transfer
*/
function bondWithdrawal(
address recipient,
uint256 amount,
bytes32 transferNonce,
uint256 bonderFee
)
external
onlyBonder
requirePositiveBalance
nonReentrant
{
bytes32 transferId = getTransferId(
getChainId(),
recipient,
amount,
transferNonce,
bonderFee,
0,
0
);
_bondWithdrawal(transferId, amount);
_fulfillWithdraw(transferId, recipient, amount, bonderFee);
}
/**
* @dev Refunds the Bonder's stake from a bonded withdrawal and counts that withdrawal against
* its TransferRoot.
* @param bonder The Bonder of the withdrawal
* @param transferId The Transfer's unique identifier
* @param rootHash The Merkle root of the TransferRoot
* @param transferRootTotalAmount The total amount being transferred in a TransferRoot
* @param transferIdTreeIndex The index of the transferId in the Merkle tree
* @param siblings The siblings of the transferId in the Merkle tree
* @param totalLeaves The total number of leaves in the Merkle tree
*/
function settleBondedWithdrawal(
address bonder,
bytes32 transferId,
bytes32 rootHash,
uint256 transferRootTotalAmount,
uint256 transferIdTreeIndex,
bytes32[] calldata siblings,
uint256 totalLeaves
)
external
{
require(
rootHash.verify(
transferId,
transferIdTreeIndex,
siblings,
totalLeaves
)
, "BRG: Invalid transfer proof");
bytes32 transferRootId = getTransferRootId(rootHash, transferRootTotalAmount);
uint256 amount = _bondedWithdrawalAmounts[bonder][transferId];
require(amount > 0, "L2_BRG: transferId has no bond");
_bondedWithdrawalAmounts[bonder][transferId] = 0;
_addToAmountWithdrawn(transferRootId, amount);
_addCredit(bonder, amount);
emit WithdrawalBondSettled(bonder, transferId, rootHash);
}
/**
* @dev Refunds the Bonder for all withdrawals that they bonded in a TransferRoot.
* @param bonder The address of the Bonder being refunded
* @param transferIds All transferIds in the TransferRoot in order
* @param totalAmount The totalAmount of the TransferRoot
*/
function settleBondedWithdrawals(
address bonder,
// transferIds _must_ be calldata or it will be mutated by Lib_MerkleTree.getMerkleRoot
bytes32[] calldata transferIds,
uint256 totalAmount
)
external
{
bytes32 rootHash = Lib_MerkleTree.getMerkleRoot(transferIds);
bytes32 transferRootId = getTransferRootId(rootHash, totalAmount);
uint256 totalBondsSettled = 0;
for(uint256 i = 0; i < transferIds.length; i++) {
uint256 transferBondAmount = _bondedWithdrawalAmounts[bonder][transferIds[i]];
if (transferBondAmount > 0) {
totalBondsSettled = totalBondsSettled.add(transferBondAmount);
_bondedWithdrawalAmounts[bonder][transferIds[i]] = 0;
}
}
_addToAmountWithdrawn(transferRootId, totalBondsSettled);
_addCredit(bonder, totalBondsSettled);
emit MultipleWithdrawalsSettled(bonder, rootHash, totalBondsSettled);
}
/* ========== External TransferRoot Rescue ========== */
/**
* @dev Allows governance to withdraw the remaining amount from a TransferRoot after the rescue delay has passed.
* @param rootHash the Merkle root of the TransferRoot
* @param originalAmount The TransferRoot's recorded total
* @param recipient The address receiving the remaining balance
*/
function rescueTransferRoot(bytes32 rootHash, uint256 originalAmount, address recipient) external onlyGovernance {
bytes32 transferRootId = getTransferRootId(rootHash, originalAmount);
TransferRoot memory transferRoot = getTransferRoot(rootHash, originalAmount);
require(transferRoot.createdAt != 0, "BRG: TransferRoot not found");
assert(transferRoot.total == originalAmount);
uint256 rescueDelayEnd = transferRoot.createdAt.add(RESCUE_DELAY);
require(block.timestamp >= rescueDelayEnd, "BRG: TransferRoot cannot be rescued before the Rescue Delay");
uint256 remainingAmount = transferRoot.total.sub(transferRoot.amountWithdrawn);
_addToAmountWithdrawn(transferRootId, remainingAmount);
_transferFromBridge(recipient, remainingAmount);
}
/* ========== Internal Functions ========== */
function _markTransferSpent(bytes32 transferId) internal {
require(!_spentTransferIds[transferId], "BRG: The transfer has already been withdrawn");
_spentTransferIds[transferId] = true;
}
function _addToAmountWithdrawn(bytes32 transferRootId, uint256 amount) internal {
TransferRoot storage transferRoot = _transferRoots[transferRootId];
require(transferRoot.total > 0, "BRG: Transfer root not found");
uint256 newAmountWithdrawn = transferRoot.amountWithdrawn.add(amount);
require(newAmountWithdrawn <= transferRoot.total, "BRG: Withdrawal exceeds TransferRoot total");
transferRoot.amountWithdrawn = newAmountWithdrawn;
}
function _setTransferRoot(bytes32 rootHash, uint256 totalAmount) internal {
bytes32 transferRootId = getTransferRootId(rootHash, totalAmount);
require(_transferRoots[transferRootId].total == 0, "BRG: Transfer root already set");
require(totalAmount > 0, "BRG: Cannot set TransferRoot totalAmount of 0");
_transferRoots[transferRootId] = TransferRoot(totalAmount, 0, block.timestamp);
emit TransferRootSet(rootHash, totalAmount);
}
function _bondWithdrawal(bytes32 transferId, uint256 amount) internal {
require(_bondedWithdrawalAmounts[msg.sender][transferId] == 0, "BRG: Withdrawal has already been bonded");
_addDebit(msg.sender, amount);
_bondedWithdrawalAmounts[msg.sender][transferId] = amount;
emit WithdrawalBonded(transferId, amount);
}
/* ========== Private Functions ========== */
/// @dev Completes the Transfer, distributes the Bonder fee and marks the Transfer as spent.
function _fulfillWithdraw(
bytes32 transferId,
address recipient,
uint256 amount,
uint256 bonderFee
) private {
_markTransferSpent(transferId);
_transferFromBridge(recipient, amount.sub(bonderFee));
if (bonderFee > 0) {
_transferFromBridge(msg.sender, bonderFee);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import "./Bridge.sol";
import "../interfaces/IMessengerWrapper.sol";
/**
* @dev L1_Bridge is responsible for the bonding and challenging of TransferRoots. All TransferRoots
* originate in the L1_Bridge through `bondTransferRoot` and are propagated up to destination L2s.
*/
abstract contract L1_Bridge is Bridge {
struct TransferBond {
address bonder;
uint256 createdAt;
uint256 totalAmount;
uint256 challengeStartTime;
address challenger;
bool challengeResolved;
}
/* ========== State ========== */
mapping(uint256 => mapping(bytes32 => uint256)) public transferRootCommittedAt;
mapping(bytes32 => TransferBond) public transferBonds;
mapping(uint256 => mapping(address => uint256)) public timeSlotToAmountBonded;
mapping(uint256 => uint256) public chainBalance;
/* ========== Config State ========== */
address public governance;
mapping(uint256 => IMessengerWrapper) public crossDomainMessengerWrappers;
mapping(uint256 => bool) public isChainIdPaused;
uint256 public challengePeriod = 1 days;
uint256 public challengeResolutionPeriod = 14 days;
uint256 public minTransferRootBondDelay = 15 minutes;
uint256 public constant CHALLENGE_AMOUNT_DIVISOR = 10;
uint256 public constant TIME_SLOT_SIZE = 4 hours;
/* ========== Events ========== */
event TransferSentToL2(
uint256 indexed chainId,
address indexed recipient,
uint256 amount,
uint256 amountOutMin,
uint256 deadline,
address indexed relayer,
uint256 relayerFee
);
event TransferRootBonded (
bytes32 indexed root,
uint256 amount
);
event TransferRootConfirmed(
uint256 indexed originChainId,
uint256 indexed destinationChainId,
bytes32 indexed rootHash,
uint256 totalAmount
);
event TransferBondChallenged(
bytes32 indexed transferRootId,
bytes32 indexed rootHash,
uint256 originalAmount
);
event ChallengeResolved(
bytes32 indexed transferRootId,
bytes32 indexed rootHash,
uint256 originalAmount
);
/* ========== Modifiers ========== */
modifier onlyL2Bridge(uint256 chainId) {
IMessengerWrapper messengerWrapper = crossDomainMessengerWrappers[chainId];
messengerWrapper.verifySender(msg.sender, msg.data);
_;
}
constructor (address[] memory bonders, address _governance) public Bridge(bonders) {
governance = _governance;
}
/* ========== Send Functions ========== */
/**
* @notice `amountOutMin` and `deadline` should be 0 when no swap is intended at the destination.
* @notice `amount` is the total amount the user wants to send including the relayer fee
* @dev Send tokens to a supported layer-2 to mint hToken and optionally swap the hToken in the
* AMM at the destination.
* @param chainId The chainId of the destination chain
* @param recipient The address receiving funds at the destination
* @param amount The amount being sent
* @param amountOutMin The minimum amount received after attempting to swap in the destination
* AMM market. 0 if no swap is intended.
* @param deadline The deadline for swapping in the destination AMM market. 0 if no
* swap is intended.
* @param relayer The address of the relayer at the destination.
* @param relayerFee The amount distributed to the relayer at the destination. This is subtracted from the `amount`.
*/
function sendToL2(
uint256 chainId,
address recipient,
uint256 amount,
uint256 amountOutMin,
uint256 deadline,
address relayer,
uint256 relayerFee
)
external
payable
{
IMessengerWrapper messengerWrapper = crossDomainMessengerWrappers[chainId];
require(messengerWrapper != IMessengerWrapper(0), "L1_BRG: chainId not supported");
require(isChainIdPaused[chainId] == false, "L1_BRG: Sends to this chainId are paused");
require(amount > 0, "L1_BRG: Must transfer a non-zero amount");
require(amount >= relayerFee, "L1_BRG: Relayer fee cannot exceed amount");
_transferToBridge(msg.sender, amount);
bytes memory message = abi.encodeWithSignature(
"distribute(address,uint256,uint256,uint256,address,uint256)",
recipient,
amount,
amountOutMin,
deadline,
relayer,
relayerFee
);
chainBalance[chainId] = chainBalance[chainId].add(amount);
messengerWrapper.sendCrossDomainMessage(message);
emit TransferSentToL2(
chainId,
recipient,
amount,
amountOutMin,
deadline,
relayer,
relayerFee
);
}
/* ========== TransferRoot Functions ========== */
/**
* @dev Setting a TransferRoot is a two step process.
* @dev 1. The TransferRoot is bonded with `bondTransferRoot`. Withdrawals can now begin on L1
* @dev and recipient L2's
* @dev 2. The TransferRoot is confirmed after `confirmTransferRoot` is called by the l2 bridge
* @dev where the TransferRoot originated.
*/
/**
* @dev Used by the Bonder to bond a TransferRoot and propagate it up to destination L2s
* @param rootHash The Merkle root of the TransferRoot Merkle tree
* @param destinationChainId The id of the destination chain
* @param totalAmount The amount destined for the destination chain
*/
function bondTransferRoot(
bytes32 rootHash,
uint256 destinationChainId,
uint256 totalAmount
)
external
onlyBonder
requirePositiveBalance
{
bytes32 transferRootId = getTransferRootId(rootHash, totalAmount);
require(transferRootCommittedAt[destinationChainId][transferRootId] == 0, "L1_BRG: TransferRoot has already been confirmed");
require(transferBonds[transferRootId].createdAt == 0, "L1_BRG: TransferRoot has already been bonded");
uint256 currentTimeSlot = getTimeSlot(block.timestamp);
uint256 bondAmount = getBondForTransferAmount(totalAmount);
timeSlotToAmountBonded[currentTimeSlot][msg.sender] = timeSlotToAmountBonded[currentTimeSlot][msg.sender].add(bondAmount);
transferBonds[transferRootId] = TransferBond(
msg.sender,
block.timestamp,
totalAmount,
uint256(0),
address(0),
false
);
_distributeTransferRoot(rootHash, destinationChainId, totalAmount);
emit TransferRootBonded(rootHash, totalAmount);
}
/**
* @dev Used by an L2 bridge to confirm a TransferRoot via cross-domain message. Once a TransferRoot
* has been confirmed, any challenge against that TransferRoot can be resolved as unsuccessful.
* @param originChainId The id of the origin chain
* @param rootHash The Merkle root of the TransferRoot Merkle tree
* @param destinationChainId The id of the destination chain
* @param totalAmount The amount destined for each destination chain
* @param rootCommittedAt The block timestamp when the TransferRoot was committed on its origin chain
*/
function confirmTransferRoot(
uint256 originChainId,
bytes32 rootHash,
uint256 destinationChainId,
uint256 totalAmount,
uint256 rootCommittedAt
)
external
onlyL2Bridge(originChainId)
{
bytes32 transferRootId = getTransferRootId(rootHash, totalAmount);
require(transferRootCommittedAt[destinationChainId][transferRootId] == 0, "L1_BRG: TransferRoot already confirmed");
require(rootCommittedAt > 0, "L1_BRG: rootCommittedAt must be greater than 0");
transferRootCommittedAt[destinationChainId][transferRootId] = rootCommittedAt;
chainBalance[originChainId] = chainBalance[originChainId].sub(totalAmount, "L1_BRG: Amount exceeds chainBalance. This indicates a layer-2 failure.");
// If the TransferRoot was never bonded, distribute the TransferRoot.
TransferBond storage transferBond = transferBonds[transferRootId];
if (transferBond.createdAt == 0) {
_distributeTransferRoot(rootHash, destinationChainId, totalAmount);
}
emit TransferRootConfirmed(originChainId, destinationChainId, rootHash, totalAmount);
}
function _distributeTransferRoot(
bytes32 rootHash,
uint256 chainId,
uint256 totalAmount
)
internal
{
// Set TransferRoot on recipient Bridge
if (chainId == getChainId()) {
// Set L1 TransferRoot
_setTransferRoot(rootHash, totalAmount);
} else {
chainBalance[chainId] = chainBalance[chainId].add(totalAmount);
IMessengerWrapper messengerWrapper = crossDomainMessengerWrappers[chainId];
require(messengerWrapper != IMessengerWrapper(0), "L1_BRG: chainId not supported");
// Set L2 TransferRoot
bytes memory setTransferRootMessage = abi.encodeWithSignature(
"setTransferRoot(bytes32,uint256)",
rootHash,
totalAmount
);
messengerWrapper.sendCrossDomainMessage(setTransferRootMessage);
}
}
/* ========== External TransferRoot Challenges ========== */
/**
* @dev Challenge a TransferRoot believed to be fraudulent
* @param rootHash The Merkle root of the TransferRoot Merkle tree
* @param originalAmount The total amount bonded for this TransferRoot
* @param destinationChainId The id of the destination chain
*/
function challengeTransferBond(bytes32 rootHash, uint256 originalAmount, uint256 destinationChainId) external payable {
bytes32 transferRootId = getTransferRootId(rootHash, originalAmount);
TransferBond storage transferBond = transferBonds[transferRootId];
require(transferRootCommittedAt[destinationChainId][transferRootId] == 0, "L1_BRG: TransferRoot has already been confirmed");
require(transferBond.createdAt != 0, "L1_BRG: TransferRoot has not been bonded");
uint256 challengePeriodEnd = transferBond.createdAt.add(challengePeriod);
require(challengePeriodEnd >= block.timestamp, "L1_BRG: TransferRoot cannot be challenged after challenge period");
require(transferBond.challengeStartTime == 0, "L1_BRG: TransferRoot already challenged");
transferBond.challengeStartTime = block.timestamp;
transferBond.challenger = msg.sender;
// Move amount from timeSlotToAmountBonded to debit
uint256 timeSlot = getTimeSlot(transferBond.createdAt);
uint256 bondAmount = getBondForTransferAmount(originalAmount);
address bonder = transferBond.bonder;
timeSlotToAmountBonded[timeSlot][bonder] = timeSlotToAmountBonded[timeSlot][bonder].sub(bondAmount);
_addDebit(transferBond.bonder, bondAmount);
// Get stake for challenge
uint256 challengeStakeAmount = getChallengeAmountForTransferAmount(originalAmount);
_transferToBridge(msg.sender, challengeStakeAmount);
emit TransferBondChallenged(transferRootId, rootHash, originalAmount);
}
/**
* @dev Resolve a challenge after the `challengeResolutionPeriod` has passed
* @param rootHash The Merkle root of the TransferRoot Merkle tree
* @param originalAmount The total amount originally bonded for this TransferRoot
* @param destinationChainId The id of the destination chain
*/
function resolveChallenge(bytes32 rootHash, uint256 originalAmount, uint256 destinationChainId) external {
bytes32 transferRootId = getTransferRootId(rootHash, originalAmount);
TransferBond storage transferBond = transferBonds[transferRootId];
require(transferBond.challengeStartTime != 0, "L1_BRG: TransferRoot has not been challenged");
require(block.timestamp > transferBond.challengeStartTime.add(challengeResolutionPeriod), "L1_BRG: Challenge period has not ended");
require(transferBond.challengeResolved == false, "L1_BRG: TransferRoot already resolved");
transferBond.challengeResolved = true;
uint256 challengeStakeAmount = getChallengeAmountForTransferAmount(originalAmount);
if (transferRootCommittedAt[destinationChainId][transferRootId] > 0) {
// Invalid challenge
if (transferBond.createdAt > transferRootCommittedAt[destinationChainId][transferRootId].add(minTransferRootBondDelay)) {
// Credit the bonder back with the bond amount plus the challenger's stake
_addCredit(transferBond.bonder, getBondForTransferAmount(originalAmount).add(challengeStakeAmount));
} else {
// If the TransferRoot was bonded before it was committed, the challenger and Bonder
// get their stake back. This discourages Bonders from tricking challengers into
// challenging a valid TransferRoots that haven't yet been committed. It also ensures
// that Bonders are not punished if a TransferRoot is bonded too soon in error.
// Return the challenger's stake
_addCredit(transferBond.challenger, challengeStakeAmount);
// Credit the bonder back with the bond amount
_addCredit(transferBond.bonder, getBondForTransferAmount(originalAmount));
}
} else {
// Valid challenge
// Burn 25% of the challengers stake
_transferFromBridge(address(0xdead), challengeStakeAmount.mul(1).div(4));
// Reward challenger with the remaining 75% of their stake plus 100% of the Bonder's stake
_addCredit(transferBond.challenger, challengeStakeAmount.mul(7).div(4));
}
emit ChallengeResolved(transferRootId, rootHash, originalAmount);
}
/* ========== Override Functions ========== */
function _additionalDebit(address bonder) internal view override returns (uint256) {
uint256 currentTimeSlot = getTimeSlot(block.timestamp);
uint256 bonded = 0;
uint256 numTimeSlots = challengePeriod / TIME_SLOT_SIZE;
for (uint256 i = 0; i < numTimeSlots; i++) {
bonded = bonded.add(timeSlotToAmountBonded[currentTimeSlot - i][bonder]);
}
return bonded;
}
function _requireIsGovernance() internal override {
require(governance == msg.sender, "L1_BRG: Caller is not the owner");
}
/* ========== External Config Management Setters ========== */
function setGovernance(address _newGovernance) external onlyGovernance {
require(_newGovernance != address(0), "L1_BRG: _newGovernance cannot be address(0)");
governance = _newGovernance;
}
function setCrossDomainMessengerWrapper(uint256 chainId, IMessengerWrapper _crossDomainMessengerWrapper) external onlyGovernance {
crossDomainMessengerWrappers[chainId] = _crossDomainMessengerWrapper;
}
function setChainIdDepositsPaused(uint256 chainId, bool isPaused) external onlyGovernance {
isChainIdPaused[chainId] = isPaused;
}
function setChallengePeriod(uint256 _challengePeriod) external onlyGovernance {
require(_challengePeriod % TIME_SLOT_SIZE == 0, "L1_BRG: challengePeriod must be divisible by TIME_SLOT_SIZE");
challengePeriod = _challengePeriod;
}
function setChallengeResolutionPeriod(uint256 _challengeResolutionPeriod) external onlyGovernance {
challengeResolutionPeriod = _challengeResolutionPeriod;
}
function setMinTransferRootBondDelay(uint256 _minTransferRootBondDelay) external onlyGovernance {
minTransferRootBondDelay = _minTransferRootBondDelay;
}
/* ========== Public Getters ========== */
function getBondForTransferAmount(uint256 amount) public pure returns (uint256) {
// Bond covers amount plus a bounty to pay a potential challenger
return amount.add(getChallengeAmountForTransferAmount(amount));
}
function getChallengeAmountForTransferAmount(uint256 amount) public pure returns (uint256) {
// Bond covers amount plus a bounty to pay a potential challenger
return amount.div(CHALLENGE_AMOUNT_DIVISOR);
}
function getTimeSlot(uint256 time) public pure returns (uint256) {
return time / TIME_SLOT_SIZE;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.12 <=0.8.9;
pragma experimental ABIEncoderV2;
interface IMessengerWrapper {
function sendCrossDomainMessage(bytes memory _calldata) external;
function verifySender(address l1BridgeCaller, bytes memory _data) external;
function confirmRoots(
bytes32[] calldata rootHashes,
uint256[] calldata destinationChainIds,
uint256[] calldata totalAmounts,
uint256[] calldata rootCommittedAts
) external;
}// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
/**
* @title Lib_MerkleTree
* @author River Keefer
*/
library Lib_MerkleTree {
/**********************
* Internal Functions *
**********************/
/**
* Calculates a merkle root for a list of 32-byte leaf hashes. WARNING: If the number
* of leaves passed in is not a power of two, it pads out the tree with zero hashes.
* If you do not know the original length of elements for the tree you are verifying,
* then this may allow empty leaves past _elements.length to pass a verification check down the line.
* Note that the _elements argument is modified, therefore it must not be used again afterwards
* @param _elements Array of hashes from which to generate a merkle root.
* @return Merkle root of the leaves, with zero hashes for non-powers-of-two (see above).
*/
function getMerkleRoot(
bytes32[] memory _elements
)
internal
pure
returns (
bytes32
)
{
require(
_elements.length > 0,
"Lib_MerkleTree: Must provide at least one leaf hash."
);
if (_elements.length == 1) {
return _elements[0];
}
uint256[16] memory defaults = [
0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563,
0x633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d,
0x890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d,
0x3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd8,
0xecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da,
0xdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da5,
0x617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d7,
0x292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead,
0xe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e10,
0x7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f82,
0xe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e83636516,
0x3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c,
0xad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e,
0xa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab,
0x4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c862,
0x2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf10
];
// Reserve memory space for our hashes.
bytes memory buf = new bytes(64);
// We'll need to keep track of left and right siblings.
bytes32 leftSibling;
bytes32 rightSibling;
// Number of non-empty nodes at the current depth.
uint256 rowSize = _elements.length;
// Current depth, counting from 0 at the leaves
uint256 depth = 0;
// Common sub-expressions
uint256 halfRowSize; // rowSize / 2
bool rowSizeIsOdd; // rowSize % 2 == 1
while (rowSize > 1) {
halfRowSize = rowSize / 2;
rowSizeIsOdd = rowSize % 2 == 1;
for (uint256 i = 0; i < halfRowSize; i++) {
leftSibling = _elements[(2 * i) ];
rightSibling = _elements[(2 * i) + 1];
assembly {
mstore(add(buf, 32), leftSibling )
mstore(add(buf, 64), rightSibling)
}
_elements[i] = keccak256(buf);
}
if (rowSizeIsOdd) {
leftSibling = _elements[rowSize - 1];
rightSibling = bytes32(defaults[depth]);
assembly {
mstore(add(buf, 32), leftSibling)
mstore(add(buf, 64), rightSibling)
}
_elements[halfRowSize] = keccak256(buf);
}
rowSize = halfRowSize + (rowSizeIsOdd ? 1 : 0);
depth++;
}
return _elements[0];
}
/**
* Verifies a merkle branch for the given leaf hash. Assumes the original length
* of leaves generated is a known, correct input, and does not return true for indices
* extending past that index (even if _siblings would be otherwise valid.)
* @param _root The Merkle root to verify against.
* @param _leaf The leaf hash to verify inclusion of.
* @param _index The index in the tree of this leaf.
* @param _siblings Array of sibline nodes in the inclusion proof, starting from depth 0 (bottom of the tree).
* @param _totalLeaves The total number of leaves originally passed into.
* @return Whether or not the merkle branch and leaf passes verification.
*/
function verify(
bytes32 _root,
bytes32 _leaf,
uint256 _index,
bytes32[] memory _siblings,
uint256 _totalLeaves
)
internal
pure
returns (
bool
)
{
require(
_totalLeaves > 0,
"Lib_MerkleTree: Total leaves must be greater than zero."
);
require(
_index < _totalLeaves,
"Lib_MerkleTree: Index out of bounds."
);
require(
_siblings.length == _ceilLog2(_totalLeaves),
"Lib_MerkleTree: Total siblings does not correctly correspond to total leaves."
);
bytes32 computedRoot = _leaf;
for (uint256 i = 0; i < _siblings.length; i++) {
if ((_index & 1) == 1) {
computedRoot = keccak256(
abi.encodePacked(
_siblings[i],
computedRoot
)
);
} else {
computedRoot = keccak256(
abi.encodePacked(
computedRoot,
_siblings[i]
)
);
}
_index >>= 1;
}
return _root == computedRoot;
}
/*********************
* Private Functions *
*********************/
/**
* Calculates the integer ceiling of the log base 2 of an input.
* @param _in Unsigned input to calculate the log.
* @return ceil(log_base_2(_in))
*/
function _ceilLog2(
uint256 _in
)
private
pure
returns (
uint256
)
{
require(
_in > 0,
"Lib_MerkleTree: Cannot compute ceil(log_2) of 0."
);
if (_in == 1) {
return 0;
}
// Find the highest set bit (will be floor(log_2)).
// Borrowed with <3 from https://github.com/ethereum/solidity-examples
uint256 val = _in;
uint256 highest = 0;
for (uint256 i = 128; i >= 1; i >>= 1) {
if (val & (uint(1) << i) - 1 << i != 0) {
highest += i;
val >>= i;
}
}
// Increment by one if this is not a perfect logarithm.
if ((uint(1) << highest) != _in) {
highest += 1;
}
return highest;
}
}{
"optimizer": {
"enabled": true,
"runs": 50000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IERC20","name":"_l1CanonicalToken","type":"address"},{"internalType":"address[]","name":"bonders","type":"address[]"},{"internalType":"address","name":"_governance","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newBonder","type":"address"}],"name":"BonderAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousBonder","type":"address"}],"name":"BonderRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transferRootId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"originalAmount","type":"uint256"}],"name":"ChallengeResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bonder","type":"address"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalBondsSettled","type":"uint256"}],"name":"MultipleWithdrawalsSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transferRootId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"originalAmount","type":"uint256"}],"name":"TransferBondChallenged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"root","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferRootBonded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"originChainId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"TransferRootConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"TransferRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deadline","type":"uint256"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"uint256","name":"relayerFee","type":"uint256"}],"name":"TransferSentToL2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bonder","type":"address"},{"indexed":true,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"}],"name":"WithdrawalBondSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalBonded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"transferNonce","type":"bytes32"}],"name":"Withdrew","type":"event"},{"inputs":[],"name":"CHALLENGE_AMOUNT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIME_SLOT_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"addBonder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"bondTransferRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"transferNonce","type":"bytes32"},{"internalType":"uint256","name":"bonderFee","type":"uint256"}],"name":"bondWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"challengePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"challengeResolutionPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"originalAmount","type":"uint256"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"}],"name":"challengeTransferBond","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"originChainId","type":"uint256"},{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"rootCommittedAt","type":"uint256"}],"name":"confirmTransferRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"crossDomainMessengerWrappers","outputs":[{"internalType":"contract IMessengerWrapper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getBondForTransferAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"}],"name":"getBondedWithdrawalAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getChallengeAmountForTransferAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"getCredit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"getDebitAndAdditionalDebit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"maybeBonder","type":"address"}],"name":"getIsBonder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"getRawDebit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"getTimeSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"transferNonce","type":"bytes32"},{"internalType":"uint256","name":"bonderFee","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"getTransferId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"getTransferRoot","outputs":[{"components":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"amountWithdrawn","type":"uint256"},{"internalType":"uint256","name":"createdAt","type":"uint256"}],"internalType":"struct Bridge.TransferRoot","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"getTransferRootId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isChainIdPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transferId","type":"bytes32"}],"name":"isTransferIdSpent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l1CanonicalToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTransferRootBondDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"removeBonder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"originalAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueTransferRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"originalAmount","type":"uint256"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"}],"name":"resolveChallenge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"relayer","type":"address"},{"internalType":"uint256","name":"relayerFee","type":"uint256"}],"name":"sendToL2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bool","name":"isPaused","type":"bool"}],"name":"setChainIdDepositsPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_challengePeriod","type":"uint256"}],"name":"setChallengePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_challengeResolutionPeriod","type":"uint256"}],"name":"setChallengeResolutionPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"contract IMessengerWrapper","name":"_crossDomainMessengerWrapper","type":"address"}],"name":"setCrossDomainMessengerWrapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernance","type":"address"}],"name":"setGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minTransferRootBondDelay","type":"uint256"}],"name":"setMinTransferRootBondDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"transferRootTotalAmount","type":"uint256"},{"internalType":"uint256","name":"transferIdTreeIndex","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"},{"internalType":"uint256","name":"totalLeaves","type":"uint256"}],"name":"settleBondedWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"bytes32[]","name":"transferIds","type":"bytes32[]"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"settleBondedWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"timeSlotToAmountBonded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transferBonds","outputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"uint256","name":"createdAt","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"challengeStartTime","type":"uint256"},{"internalType":"address","name":"challenger","type":"address"},{"internalType":"bool","name":"challengeResolved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transferRootCommittedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"transferNonce","type":"bytes32"},{"internalType":"uint256","name":"bonderFee","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"transferRootTotalAmount","type":"uint256"},{"internalType":"uint256","name":"transferIdTreeIndex","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"},{"internalType":"uint256","name":"totalLeaves","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a060405262015180600e5562127500600f556103846010553480156200002557600080fd5b5060405162004ef438038062004ef48339810160408190526200004891620001b6565b81818180600160008190555060005b81518110156200016657600160008383815181106200007257fe5b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1615620000c25760405162461bcd60e51b8152600401620000b9906200028a565b60405180910390fd5b6001806000848481518110620000d457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055508181815181106200012057fe5b60200260200101516001600160a01b03167f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e2360405160405180910390a260010162000057565b5050600b80546001600160a01b0319166001600160a01b0393909316929092179091555050505060601b6001600160601b0319166080526200031f565b8051620001b08162000306565b92915050565b600080600060608486031215620001cb578283fd5b8351620001d88162000306565b602085810151919450906001600160401b03811115620001f6578384fd5b8501601f8101871362000207578384fd5b80516200021e6200021882620002e6565b620002bf565b81815283810190838501858402850186018b10156200023b578788fd5b8794505b838510156200026957620002548b82620001a3565b8352600194909401939185019185016200023f565b508096505050505050620002818560408601620001a3565b90509250925092565b6020808252818101527f4143543a2043616e6e6f7420616464206475706c696361746520626f6e646572604082015260600190565b6040518181016001600160401b0381118282101715620002de57600080fd5b604052919050565b60006001600160401b03821115620002fc578081fd5b5060209081020190565b6001600160a01b03811681146200031c57600080fd5b50565b60805160601c614bad6200034760003980611ba552806127f252806128ef5250614bad6000f3fe6080604052600436106102fd5760003560e01c80638d8798bf1161018f578063cbd1642e116100e1578063eecd57e61161008a578063fa2a69a311610064578063fa2a69a314610834578063fc110b6714610854578063ffa9286c14610874576102fd565b8063eecd57e6146107df578063ef6ebe5e146107ff578063f3f480d91461081f576102fd565b8063d5ef7551116100bb578063d5ef75511461078c578063deace8f5146107ac578063e19be150146107bf576102fd565b8063cbd1642e1461071f578063ce803b4f1461073f578063d44481631461076c576102fd565b8063ab033ea911610143578063b162717e1161011d578063b162717e146106ca578063b7a0bda6146106ea578063c7525dd3146106ff576102fd565b8063ab033ea914610677578063adc9772e14610697578063af215f94146106aa576102fd565b806398c4f76d1161017457806398c4f76d14610622578063a239f5ee14610637578063a35962f314610657576102fd565b80638d8798bf146105e2578063960a7afa14610602576102fd565b80633a7af631116102535780635aa6e675116101fc5780637398d282116101d65780637398d2821461058d578063767631d5146105ad57806381707b80146105c2576102fd565b80635aa6e675146105365780635d475fdd146105585780636cff06a714610578576102fd565b80635325937f1161022d5780635325937f146104c457806357344e6f146104e45780635a7e108314610504576102fd565b80633a7af631146104625780633b8fea281461048f5780634de8c6e6146104af576102fd565b806323c452cd116102b5578063302830ab1161028f578063302830ab1461040d5780633408e4701461042d57806339ada66914610442576102fd565b806323c452cd146103ad5780632b85dcc9146103cd5780632e17de78146103ed576102fd565b806313948c76116102e657806313948c7614610344578063149420241461037a5780631bbe15ea1461039a576102fd565b806304e6c2c0146103025780630f7aadb714610324575b600080fd5b34801561030e57600080fd5b5061032261031d366004613670565b610894565b005b34801561033057600080fd5b5061032261033f3660046137cd565b61097e565b34801561035057600080fd5b5061036461035f366004613670565b610adf565b6040516103719190613c76565b60405180910390f35b34801561038657600080fd5b50610322610395366004613a27565b610b0b565b6103226103a836600461390d565b610b51565b3480156103b957600080fd5b506103226103c8366004613793565b610dbb565b3480156103d957600080fd5b506103646103e836600461389c565b610ecd565b3480156103f957600080fd5b5061032261040836600461389c565b610ed5565b34801561041957600080fd5b506103646104283660046136e6565b610fcb565b34801561043957600080fd5b50610364611003565b34801561044e57600080fd5b5061032261045d36600461389c565b611007565b34801561046e57600080fd5b5061048261047d36600461389c565b611014565b6040516103719190613c6b565b34801561049b57600080fd5b506103646104aa3660046138b4565b611029565b3480156104bb57600080fd5b50610364611046565b3480156104d057600080fd5b506103226104df366004613670565b61104c565b3480156104f057600080fd5b506103646104ff366004613670565b61112e565b34801561051057600080fd5b5061052461051f36600461389c565b611156565b60405161037196959493929190613bdb565b34801561054257600080fd5b5061054b6111ba565b6040516103719190613af9565b34801561056457600080fd5b5061032261057336600461389c565b6111d6565b34801561058457600080fd5b5061036461121f565b34801561059957600080fd5b506103646105a8366004613938565b611225565b3480156105b957600080fd5b50610364611242565b3480156105ce57600080fd5b506103226105dd36600461390d565b611248565b3480156105ee57600080fd5b506103226105fd36600461390d565b6114fc565b34801561060e57600080fd5b5061036461061d3660046138b4565b6117ca565b34801561062e57600080fd5b506103646117fd565b34801561064357600080fd5b5061036461065236600461389c565b611802565b34801561066357600080fd5b5061054b61067236600461389c565b61180f565b34801561068357600080fd5b50610322610692366004613670565b611837565b6103226106a53660046136e6565b6118d3565b3480156106b657600080fd5b506103646106c5366004613967565b6119e4565b3480156106d657600080fd5b506103226106e536600461368c565b611a26565b3480156106f657600080fd5b5061054b611ba3565b34801561070b57600080fd5b5061032261071a366004613711565b611bc7565b34801561072b57600080fd5b5061032261073a3660046138d5565b611d4e565b34801561074b57600080fd5b5061075f61075a3660046138b4565b611e45565b6040516103719190614a53565b34801561077857600080fd5b50610322610787366004613938565b611e9a565b34801561079857600080fd5b506104826107a7366004613670565b611ef5565b6103226107ba3660046139bf565b611f20565b3480156107cb57600080fd5b506103646107da36600461389c565b6121fd565b3480156107eb57600080fd5b506103226107fa36600461389c565b612212565b34801561080b57600080fd5b5061032261081a366004613a4b565b61221f565b34801561082b57600080fd5b50610364612408565b34801561084057600080fd5b5061048261084f36600461389c565b61240e565b34801561086057600080fd5b5061036461086f36600461389c565b612423565b34801561088057600080fd5b5061036461088f366004613670565b612435565b61089c61246f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602081905260409091205460ff1615151461090a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061400a565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4234ba611d325b3ba434c4e1b037967b955b1274d4185ee9847b7491111a48ff9190a250565b600260005414156109bb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148a8565b600260009081556109d86109cd611003565b8e8e8e8e8e8e6119e4565b9050610a1e81868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d9594939250889150506124c2565b610a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614588565b6000610a6088886117ca565b9050610a6c818e61262c565b610a79828f8f60006126cc565b8d73ffffffffffffffffffffffffffffffffffffffff16827f9475cdbde5fc71fe2ccd413c82878ee54d061b9f74f9e2e1a03ff1178821502c8f8f604051610ac2929190613acf565b60405180910390a350506001600055505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020545b919050565b610b1361246f565b6000918252600d602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000610b5d84846117ca565b600081815260086020908152604080832086845260078352818420858552909252909120549192509015610bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614405565b6001810154610bf8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613d83565b6000610c13600e5483600101546126f390919063ffffffff16565b905042811015610c4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906145bf565b600382015415610c8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613f50565b4260038301556004820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556001820154600090610cce90610ecd565b90506000610cdb876121fd565b8454600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9094168084529390915290205491925090610d1e9083612739565b600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff80871685529252909120919091558554610d5f91168361277b565b6000610d6a89611802565b9050610d7633826127d8565b89877fec2697dcba539a0ac947cdf1f6d0b6314c065429eca8be2435859b10209d4c278b604051610da79190613c76565b60405180910390a350505050505050505050565b3360009081526001602052604090205460ff16610e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614551565b60026000541415610e41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148a8565b60026000908155610e5f610e53611003565b868686866000806119e4565b9050610e6b818561281e565b610e77818686856126cc565b506001600055610e8633612435565b610e8f3361112e565b1015610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144bf565b50505050565b613840900490565b60026000541415610f12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148a8565b6002600055610f21338261277b565b610f2b33826128d5565b3373ffffffffffffffffffffffffffffffffffffffff167f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd82604051610f719190613c76565b60405180910390a26001600055610f8733612435565b610f903361112e565b1015610fc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144bf565b50565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602090815260408083208484529091529020545b92915050565b4690565b61100f61246f565b601055565b60009081526005602052604090205460ff1690565b600760209081526000928352604080842090915290825290205481565b61384081565b61105461246f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff16156110b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e4e565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909217909155517f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e239190a250565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b6008602052600090815260409020805460018201546002830154600384015460049094015473ffffffffffffffffffffffffffffffffffffffff93841694929391929181169074010000000000000000000000000000000000000000900460ff1686565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b6111de61246f565b61384081061561121a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613cef565b600e55565b60105481565b600960209081526000928352604080842090915290825290205481565b600f5481565b600061125484846117ca565b60008181526008602052604090206003810154919250906112a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906147ee565b600f5460038201546112b2916126f3565b42116112ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614654565b600481015474010000000000000000000000000000000000000000900460ff1615611341576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613ef3565b6004810180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055600061138d85611802565b6000858152600760209081526040808320878452909152902054909150156114685760105460008581526007602090815260408083208784529091529020546113d5916126f3565b826001015411156114195781546114149073ffffffffffffffffffffffffffffffffffffffff1661140f83611409896121fd565b906126f3565b612916565b611463565b600482015461143e9073ffffffffffffffffffffffffffffffffffffffff1682612916565b81546114639073ffffffffffffffffffffffffffffffffffffffff1661140f876121fd565b6114bb565b61148961dead611484600461147e856001612973565b906129c7565b6128d5565b6004808301546114bb9173ffffffffffffffffffffffffffffffffffffffff9091169061140f9061147e856007612973565b85837f4a99228a8a6d774d261be57ab0ed833bb1bae1f22bbbd3d4767b75ad03fdddf7876040516114ec9190613c76565b60405180910390a3505050505050565b3360009081526001602052604090205460ff16611545576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614551565b600061155184836117ca565b6000848152600760209081526040808320848452909152902054909150156115a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614405565b600081815260086020526040902060010154156115ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614999565b60006115f942610ecd565b90506000611606846121fd565b600083815260096020908152604080832033845290915290205490915061162d90826126f3565b60008381526009602090815260408083203380855290835281842094909455805160c08101825293845242848301908152848201898152606086018581526080870186815260a088018781528b88526008909652939095209551865473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161788559251600188015590516002870155935160038601559051600490940180549251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff95909416929091169190911792909216179055611740868686612a13565b857fa57b3e1f3af9eca02201028629700658608222c365064584cfe65d9630ef4f7b856040516117709190613c76565b60405180910390a250505061178433612435565b61178d3361112e565b10156117c5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144bf565b505050565b600082826040516020016117df929190613acf565b60405160208183030381529060405280519060200120905092915050565b600a81565b6000610ffd82600a6129c7565b600c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61183f61246f565b73ffffffffffffffffffffffffffffffffffffffff811661188c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148df565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60026000541415611910576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148a8565b6002600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602081905260409091205460ff16151514611979576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061400a565b61198333826127d8565b61198d8282612916565b8173ffffffffffffffffffffffffffffffffffffffff167febedb8b3c678666e7f36970bc8f57abf6d8fa2e828c0da91ea5b75bf68ed101a826040516119d39190613c76565b60405180910390a250506001600055565b600087878787878787604051602001611a039796959493929190614a74565b604051602081830303815290604052805190602001209050979650505050505050565b6000611a64848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612bc992505050565b90506000611a7282846117ca565b90506000805b85811015611b365773ffffffffffffffffffffffffffffffffffffffff8816600090815260066020526040812081898985818110611ab257fe5b9050602002013581526020019081526020016000205490506000811115611b2d57611add83826126f3565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040812091945090818a8a86818110611b1357fe5b905060200201358152602001908152602001600020819055505b50600101611a78565b50611b41828261262c565b611b4b8782612916565b828773ffffffffffffffffffffffffffffffffffffffff167f78e830d08be9d5f957414c84d685c061ecbd8467be98b42ebb64f0118b57d2ff83604051611b929190613c76565b60405180910390a350505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b611c0b87858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9594939250879150506124c2565b611c41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614588565b6000611c4d87876117ca565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c845290915290205490915080611cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613de0565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c8452909152812055611cf3828261262c565b611cfd8a82612916565b87898b73ffffffffffffffffffffffffffffffffffffffff167f84eb21b24c31b27a3bc67dde4a598aad06db6e9415cd66544492b9616996143c60405160405180910390a450505050505050505050565b611d5661246f565b6000611d6284846117ca565b9050611d6c6135e7565b611d768585611e45565b9050806040015160001415611db7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e85565b80518414611dc157fe5b6040810151600090611dd6906249d4006126f3565b905080421015611e12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613fad565b60208201518251600091611e269190612739565b9050611e32848261262c565b611e3c85826128d5565b50505050505050565b611e4d6135e7565b60046000611e5b85856117ca565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b611ea261246f565b6000918252600c602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b6000878152600c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611f7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614280565b6000888152600d602052604090205460ff1615611fc5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614041565b60008611611fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613c92565b81861015612039576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906149f6565b61204333876127d8565b606087878787878760405160240161206096959493929190613c23565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcc29a3060000000000000000000000000000000000000000000000000000000017905260008c8152600a90915220549091506120f090886126f3565b60008a8152600a60205260409081902091909155517f419cb55000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063419cb55090612154908490600401613c7f565b600060405180830381600087803b15801561216e57600080fd5b505af1158015612182573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a7f0a0607688c86ec1775abcdbab7b33a3a35a6c9cde677c9be880150c231cc6b0b8a8a8a896040516121ea9493929190614aba565b60405180910390a4505050505050505050565b6000610ffd61220b83611802565b83906126f3565b61221a61246f565b600f55565b6000858152600c60205260408082205490517f99178dd8000000000000000000000000000000000000000000000000000000008152879273ffffffffffffffffffffffffffffffffffffffff9092169182916399178dd891612288913391903690600401613b1a565b600060405180830381600087803b1580156122a257600080fd5b505af11580156122b6573d6000803e3d6000fd5b5050505060006122c687866117ca565b60008781526007602090815260408083208484529091529020549091501561231a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061434b565b60008411612354576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906140d5565b600086815260076020908152604080832084845282529182902086905581516080810190925260468083526123a5928892909190614b329083013960008b8152600a60205260409020549190613000565b6000898152600a6020908152604080832093909355838252600890522060018101546123d6576123d6888888612a13565b87878a7ffdfb0eefa96935b8a8c0edf528e125dc6f3934fdbbfce31b38967e8ff413dccd896040516121ea9190613c76565b600e5481565b600d6020526000908152604090205460ff1681565b600a6020526000908152604090205481565b6000610ffd61244383613046565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902054906126f3565b600b5473ffffffffffffffffffffffffffffffffffffffff1633146124c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613d4c565b565b60008082116124fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614462565b818410612536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614223565b61253f826130c4565b835114612578576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906146b1565b8460005b845181101561261f5785600116600114156125d45784818151811061259d57fe5b6020026020010151826040516020016125b7929190613acf565b604051602081830303815290604052805190602001209150612613565b818582815181106125e157fe5b60200260200101516040516020016125fa929190613acf565b6040516020818303038152906040528051906020012091505b600195861c950161257c565b5090951495945050505050565b60008281526004602052604090208054612672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e17565b600181015460009061268490846126f3565b82549091508111156126c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061484b565b6001909101555050565b6126d584613173565b6126e3836114848484612739565b8015610ec757610ec733826128d5565b600082820183811015612732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613ebc565b9392505050565b600082821115612775576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061409e565b50900390565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409020546127ab90826126f3565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526003602052604090209190915550565b61281a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168330846131f5565b5050565b33600090815260066020908152604080832085845290915290205415612870576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614734565b61287a338261277b565b336000908152600660209081526040808320858452909152908190208290555182907f0c3d250c7831051e78aa6a56679e590374c7c424415ffe4aa474491def2fe705906128c9908490613c76565b60405180910390a25050565b61281a73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168383613298565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090205461294690826126f3565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090209190915550565b60008261298257506000610ffd565b8282028284828161298f57fe5b0414612732576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906143a8565b6000808211612a02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061418f565b818381612a0b57fe5b049392505050565b612a1b611003565b821415612a3157612a2c83826132b7565b6117c5565b6000828152600a6020526040902054612a4a90826126f3565b6000838152600a6020908152604080832093909355600c9052205473ffffffffffffffffffffffffffffffffffffffff1680612ab2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614280565b60608483604051602401612ac7929190613acf565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ffd31c5ba00000000000000000000000000000000000000000000000000000000179052517f419cb55000000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff83169063419cb55090612b90908490600401613c7f565b600060405180830381600087803b158015612baa57600080fd5b505af1158015612bbe573d6000803e3d6000fd5b505050505050505050565b600080825111612c05576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061493c565b815160011415612c2b5781600081518110612c1c57fe5b60200260200101519050610b06565b612c33613608565b5060408051610200810182527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381527f633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d60208201527f890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d818301527f3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd86060808301919091527fecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da60808301527fdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da560a08301527f617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d760c08301527f292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead60e08301527fe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e106101008301527f7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f826101208301527fe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e836365166101408301527f3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c6101608301527fad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e6101808301527fa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab6101a08301527f4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c8626101c08301527f2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf106101e0830152825183815280820184529192909190602082018180368337505085519192506000918291508180805b6001841115612fdc5750506002820460018084161460005b82811015612f58578a8160020281518110612eff57fe5b602002602001015196508a8160020260010181518110612f1b57fe5b6020026020010151955086602089015285604089015287805190602001208b8281518110612f4557fe5b6020908102919091010152600101612ee8565b508015612fbb57896001850381518110612f6e57fe5b60200260200101519550878360108110612f8457fe5b602002015160001b945085602088015284604088015286805190602001208a8381518110612fae57fe5b6020026020010181815250505b80612fc7576000612fca565b60015b60ff1682019350600190920191612ed0565b89600081518110612fe957fe5b602002602001015198505050505050505050919050565b6000818484111561303e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019190613c7f565b505050900390565b60008061305242610ecd565b9050600080613840600e548161306457fe5b04905060005b818110156130ba57808403600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a1684529091529020546130b09084906126f3565b925060010161306a565b5090949350505050565b60008082116130ff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906142b7565b816001141561311057506000610b06565b81600060805b6001811061315e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001821b01811b8316156131565791821c91908101905b60011c613116565b506001811b8414612732576001019392505050565b60008181526005602052604090205460ff16156131bc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906141c6565b600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b610ec7846323b872dd60e01b85858560405160240161321693929190613b84565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526133bf565b6117c58363a9059cbb60e01b8484604051602401613216929190613bb5565b60006132c383836117ca565b6000818152600460205260409020549091501561330c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614314565b60008211613346576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144f4565b6040805160608101825283815260006020808301828152428486019081528684526004909252918490209251835590516001830155516002909101555183907fb33d2162aead99dab59e77a7a67ea025b776bf8ca8079e132afdf9b23e03bd42906133b2908590613c76565b60405180910390a2505050565b6060613421826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166134759092919063ffffffff16565b8051909150156117c5578080602001905181019061343f9190613880565b6117c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614791565b6060613484848460008561348c565b949350505050565b6060824710156134c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614132565b6134d18561358e565b613507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061461d565b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516135319190613add565b60006040518083038185875af1925050503d806000811461356e576040519150601f19603f3d011682016040523d82523d6000602084013e613573565b606091505b5091509150613583828286613594565b979650505050505050565b3b151590565b606083156135a3575081612732565b8251156135b35782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019190613c7f565b60405180606001604052806000815260200160008152602001600081525090565b6040518061020001604052806010906020820280368337509192915050565b60008083601f840112613638578182fd5b50813567ffffffffffffffff81111561364f578182fd5b602083019150836020808302850101111561366957600080fd5b9250929050565b600060208284031215613681578081fd5b813561273281614b01565b600080600080606085870312156136a1578283fd5b84356136ac81614b01565b9350602085013567ffffffffffffffff8111156136c7578384fd5b6136d387828801613627565b9598909750949560400135949350505050565b600080604083850312156136f8578182fd5b823561370381614b01565b946020939093013593505050565b60008060008060008060008060e0898b03121561372c578384fd5b883561373781614b01565b97506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff81111561376e578384fd5b61377a8b828c01613627565b999c989b50969995989497949560c00135949350505050565b600080600080608085870312156137a8578384fd5b84356137b381614b01565b966020860135965060408601359560600135945092505050565b6000806000806000806000806000806000806101608d8f0312156137ef578384fd5b6137f98d35614b01565b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d0135935067ffffffffffffffff6101208e0135111561384f578283fd5b6138608e6101208f01358f01613627565b81945080935050506101408d013590509295989b509295989b509295989b565b600060208284031215613891578081fd5b815161273281614b23565b6000602082840312156138ad578081fd5b5035919050565b600080604083850312156138c6578182fd5b50508035926020909101359150565b6000806000606084860312156138e9578283fd5b8335925060208401359150604084013561390281614b01565b809150509250925092565b600080600060608486031215613921578081fd5b505081359360208301359350604090920135919050565b6000806040838503121561394a578182fd5b82359150602083013561395c81614b01565b809150509250929050565b600080600080600080600060e0888a031215613981578081fd5b87359650602088013561399381614b01565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600080600060e0888a0312156139d9578081fd5b8735965060208801356139eb81614b01565b955060408801359450606088013593506080880135925060a0880135613a1081614b01565b8092505060c0880135905092959891949750929550565b60008060408385031215613a39578182fd5b82359150602083013561395c81614b23565b600080600080600060a08688031215613a62578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008151808452613a9d816020860160208601614ad5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b918252602082015260400190565b60008251613aef818460208701614ad5565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff851682526040602083015282604083015282846060840137818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015290151560a082015260c00190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b901515815260200190565b90815260200190565b6000602082526127326020830184613a85565b60208082526027908201527f4c315f4252473a204d757374207472616e736665722061206e6f6e2d7a65726f60408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4c315f4252473a206368616c6c656e6765506572696f64206d7573742062652060408201527f646976697369626c652062792054494d455f534c4f545f53495a450000000000606082015260800190565b6020808252601f908201527f4c315f4252473a2043616c6c6572206973206e6f7420746865206f776e657200604082015260600190565b60208082526028908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e20626f6e646564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f4c325f4252473a207472616e73666572496420686173206e6f20626f6e640000604082015260600190565b6020808252601c908201527f4252473a205472616e7366657220726f6f74206e6f7420666f756e6400000000604082015260600190565b6020808252601e908201527f4143543a204164647265737320697320616c726561647920626f6e6465720000604082015260600190565b6020808252601b908201527f4252473a205472616e73666572526f6f74206e6f7420666f756e640000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526025908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792072657360408201527f6f6c766564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792063686160408201527f6c6c656e67656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4252473a205472616e73666572526f6f742063616e6e6f74206265207265736360408201527f756564206265666f726520746865205265736375652044656c61790000000000606082015260800190565b6020808252601a908201527f4143543a2041646472657373206973206e6f7420626f6e646572000000000000604082015260600190565b60208082526028908201527f4c315f4252473a2053656e647320746f207468697320636861696e496420617260408201527f6520706175736564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602e908201527f4c315f4252473a20726f6f74436f6d6d69747465644174206d7573742062652060408201527f67726561746572207468616e2030000000000000000000000000000000000000606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252602c908201527f4252473a20546865207472616e736665722068617320616c726561647920626560408201527f656e2077697468647261776e0000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4c69625f4d65726b6c65547265653a20496e646578206f7574206f6620626f7560408201527f6e64732e00000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f4c315f4252473a20636861696e4964206e6f7420737570706f72746564000000604082015260600190565b60208082526030908201527f4c69625f4d65726b6c65547265653a2043616e6e6f7420636f6d70757465206360408201527f65696c286c6f675f3229206f6620302e00000000000000000000000000000000606082015260800190565b6020808252601e908201527f4252473a205472616e7366657220726f6f7420616c7265616479207365740000604082015260600190565b60208082526026908201527f4c315f4252473a205472616e73666572526f6f7420616c726561647920636f6e60408201527f6669726d65640000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20636f6e6669726d65640000000000000000000000000000000000606082015260800190565b60208082526037908201527f4c69625f4d65726b6c65547265653a20546f74616c206c6561766573206d757360408201527f742062652067726561746572207468616e207a65726f2e000000000000000000606082015260800190565b6020808252818101527f4143543a204e6f7420656e6f75676820617661696c61626c6520637265646974604082015260600190565b6020808252602d908201527f4252473a2043616e6e6f7420736574205472616e73666572526f6f7420746f7460408201527f616c416d6f756e74206f66203000000000000000000000000000000000000000606082015260800190565b60208082526019908201527f4143543a2043616c6c6572206973206e6f7420626f6e64657200000000000000604082015260600190565b6020808252601b908201527f4252473a20496e76616c6964207472616e736665722070726f6f660000000000604082015260600190565b602080825260409082018190527f4c315f4252473a205472616e73666572526f6f742063616e6e6f742062652063908201527f68616c6c656e676564206166746572206368616c6c656e676520706572696f64606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526026908201527f4c315f4252473a204368616c6c656e676520706572696f6420686173206e6f7460408201527f20656e6465640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252604d908201527f4c69625f4d65726b6c65547265653a20546f74616c207369626c696e6773206460408201527f6f6573206e6f7420636f72726563746c7920636f72726573706f6e6420746f2060608201527f746f74616c206c65617665732e00000000000000000000000000000000000000608082015260a00190565b60208082526027908201527f4252473a205769746864726177616c2068617320616c7265616479206265656e60408201527f20626f6e64656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e206368616c6c656e6765640000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4252473a205769746864726177616c2065786365656473205472616e7366657260408201527f526f6f7420746f74616c00000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4c315f4252473a205f6e6577476f7665726e616e63652063616e6e6f7420626560408201527f2061646472657373283029000000000000000000000000000000000000000000606082015260800190565b60208082526034908201527f4c69625f4d65726b6c65547265653a204d7573742070726f766964652061742060408201527f6c65617374206f6e65206c65616620686173682e000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20626f6e6465640000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f4c315f4252473a2052656c61796572206665652063616e6e6f7420657863656560408201527f6420616d6f756e74000000000000000000000000000000000000000000000000606082015260800190565b81518152602080830151908201526040918201519181019190915260600190565b96875273ffffffffffffffffffffffffffffffffffffffff95909516602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b93845260208401929092526040830152606082015260800190565b60005b83811015614af0578181015183820152602001614ad8565b83811115610ec75750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114610fc857600080fd5b8015158114610fc857600080fdfe4c315f4252473a20416d6f756e74206578636565647320636861696e42616c616e63652e205468697320696e646963617465732061206c617965722d32206661696c7572652ea2646970667358221220f548b4a85c13af0cf10d4b98bc2d4014c0fb5bdcb08efee30389464c055edb0564736f6c634300060c0033000000000000000000000000ae78736cd615f374d3085123a210448e74fc63930000000000000000000000000000000000000000000000000000000000000060000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000002a6303e6b99d451df3566068ebb110708335658f
Deployed Bytecode
0x6080604052600436106102fd5760003560e01c80638d8798bf1161018f578063cbd1642e116100e1578063eecd57e61161008a578063fa2a69a311610064578063fa2a69a314610834578063fc110b6714610854578063ffa9286c14610874576102fd565b8063eecd57e6146107df578063ef6ebe5e146107ff578063f3f480d91461081f576102fd565b8063d5ef7551116100bb578063d5ef75511461078c578063deace8f5146107ac578063e19be150146107bf576102fd565b8063cbd1642e1461071f578063ce803b4f1461073f578063d44481631461076c576102fd565b8063ab033ea911610143578063b162717e1161011d578063b162717e146106ca578063b7a0bda6146106ea578063c7525dd3146106ff576102fd565b8063ab033ea914610677578063adc9772e14610697578063af215f94146106aa576102fd565b806398c4f76d1161017457806398c4f76d14610622578063a239f5ee14610637578063a35962f314610657576102fd565b80638d8798bf146105e2578063960a7afa14610602576102fd565b80633a7af631116102535780635aa6e675116101fc5780637398d282116101d65780637398d2821461058d578063767631d5146105ad57806381707b80146105c2576102fd565b80635aa6e675146105365780635d475fdd146105585780636cff06a714610578576102fd565b80635325937f1161022d5780635325937f146104c457806357344e6f146104e45780635a7e108314610504576102fd565b80633a7af631146104625780633b8fea281461048f5780634de8c6e6146104af576102fd565b806323c452cd116102b5578063302830ab1161028f578063302830ab1461040d5780633408e4701461042d57806339ada66914610442576102fd565b806323c452cd146103ad5780632b85dcc9146103cd5780632e17de78146103ed576102fd565b806313948c76116102e657806313948c7614610344578063149420241461037a5780631bbe15ea1461039a576102fd565b806304e6c2c0146103025780630f7aadb714610324575b600080fd5b34801561030e57600080fd5b5061032261031d366004613670565b610894565b005b34801561033057600080fd5b5061032261033f3660046137cd565b61097e565b34801561035057600080fd5b5061036461035f366004613670565b610adf565b6040516103719190613c76565b60405180910390f35b34801561038657600080fd5b50610322610395366004613a27565b610b0b565b6103226103a836600461390d565b610b51565b3480156103b957600080fd5b506103226103c8366004613793565b610dbb565b3480156103d957600080fd5b506103646103e836600461389c565b610ecd565b3480156103f957600080fd5b5061032261040836600461389c565b610ed5565b34801561041957600080fd5b506103646104283660046136e6565b610fcb565b34801561043957600080fd5b50610364611003565b34801561044e57600080fd5b5061032261045d36600461389c565b611007565b34801561046e57600080fd5b5061048261047d36600461389c565b611014565b6040516103719190613c6b565b34801561049b57600080fd5b506103646104aa3660046138b4565b611029565b3480156104bb57600080fd5b50610364611046565b3480156104d057600080fd5b506103226104df366004613670565b61104c565b3480156104f057600080fd5b506103646104ff366004613670565b61112e565b34801561051057600080fd5b5061052461051f36600461389c565b611156565b60405161037196959493929190613bdb565b34801561054257600080fd5b5061054b6111ba565b6040516103719190613af9565b34801561056457600080fd5b5061032261057336600461389c565b6111d6565b34801561058457600080fd5b5061036461121f565b34801561059957600080fd5b506103646105a8366004613938565b611225565b3480156105b957600080fd5b50610364611242565b3480156105ce57600080fd5b506103226105dd36600461390d565b611248565b3480156105ee57600080fd5b506103226105fd36600461390d565b6114fc565b34801561060e57600080fd5b5061036461061d3660046138b4565b6117ca565b34801561062e57600080fd5b506103646117fd565b34801561064357600080fd5b5061036461065236600461389c565b611802565b34801561066357600080fd5b5061054b61067236600461389c565b61180f565b34801561068357600080fd5b50610322610692366004613670565b611837565b6103226106a53660046136e6565b6118d3565b3480156106b657600080fd5b506103646106c5366004613967565b6119e4565b3480156106d657600080fd5b506103226106e536600461368c565b611a26565b3480156106f657600080fd5b5061054b611ba3565b34801561070b57600080fd5b5061032261071a366004613711565b611bc7565b34801561072b57600080fd5b5061032261073a3660046138d5565b611d4e565b34801561074b57600080fd5b5061075f61075a3660046138b4565b611e45565b6040516103719190614a53565b34801561077857600080fd5b50610322610787366004613938565b611e9a565b34801561079857600080fd5b506104826107a7366004613670565b611ef5565b6103226107ba3660046139bf565b611f20565b3480156107cb57600080fd5b506103646107da36600461389c565b6121fd565b3480156107eb57600080fd5b506103226107fa36600461389c565b612212565b34801561080b57600080fd5b5061032261081a366004613a4b565b61221f565b34801561082b57600080fd5b50610364612408565b34801561084057600080fd5b5061048261084f36600461389c565b61240e565b34801561086057600080fd5b5061036461086f36600461389c565b612423565b34801561088057600080fd5b5061036461088f366004613670565b612435565b61089c61246f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602081905260409091205460ff1615151461090a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061400a565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4234ba611d325b3ba434c4e1b037967b955b1274d4185ee9847b7491111a48ff9190a250565b600260005414156109bb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148a8565b600260009081556109d86109cd611003565b8e8e8e8e8e8e6119e4565b9050610a1e81868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d9594939250889150506124c2565b610a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614588565b6000610a6088886117ca565b9050610a6c818e61262c565b610a79828f8f60006126cc565b8d73ffffffffffffffffffffffffffffffffffffffff16827f9475cdbde5fc71fe2ccd413c82878ee54d061b9f74f9e2e1a03ff1178821502c8f8f604051610ac2929190613acf565b60405180910390a350506001600055505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020545b919050565b610b1361246f565b6000918252600d602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000610b5d84846117ca565b600081815260086020908152604080832086845260078352818420858552909252909120549192509015610bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614405565b6001810154610bf8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613d83565b6000610c13600e5483600101546126f390919063ffffffff16565b905042811015610c4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906145bf565b600382015415610c8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613f50565b4260038301556004820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556001820154600090610cce90610ecd565b90506000610cdb876121fd565b8454600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9094168084529390915290205491925090610d1e9083612739565b600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff80871685529252909120919091558554610d5f91168361277b565b6000610d6a89611802565b9050610d7633826127d8565b89877fec2697dcba539a0ac947cdf1f6d0b6314c065429eca8be2435859b10209d4c278b604051610da79190613c76565b60405180910390a350505050505050505050565b3360009081526001602052604090205460ff16610e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614551565b60026000541415610e41576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148a8565b60026000908155610e5f610e53611003565b868686866000806119e4565b9050610e6b818561281e565b610e77818686856126cc565b506001600055610e8633612435565b610e8f3361112e565b1015610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144bf565b50505050565b613840900490565b60026000541415610f12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148a8565b6002600055610f21338261277b565b610f2b33826128d5565b3373ffffffffffffffffffffffffffffffffffffffff167f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd82604051610f719190613c76565b60405180910390a26001600055610f8733612435565b610f903361112e565b1015610fc8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144bf565b50565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602090815260408083208484529091529020545b92915050565b4690565b61100f61246f565b601055565b60009081526005602052604090205460ff1690565b600760209081526000928352604080842090915290825290205481565b61384081565b61105461246f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff16156110b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e4e565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909217909155517f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e239190a250565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b6008602052600090815260409020805460018201546002830154600384015460049094015473ffffffffffffffffffffffffffffffffffffffff93841694929391929181169074010000000000000000000000000000000000000000900460ff1686565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b6111de61246f565b61384081061561121a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613cef565b600e55565b60105481565b600960209081526000928352604080842090915290825290205481565b600f5481565b600061125484846117ca565b60008181526008602052604090206003810154919250906112a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906147ee565b600f5460038201546112b2916126f3565b42116112ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614654565b600481015474010000000000000000000000000000000000000000900460ff1615611341576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613ef3565b6004810180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055600061138d85611802565b6000858152600760209081526040808320878452909152902054909150156114685760105460008581526007602090815260408083208784529091529020546113d5916126f3565b826001015411156114195781546114149073ffffffffffffffffffffffffffffffffffffffff1661140f83611409896121fd565b906126f3565b612916565b611463565b600482015461143e9073ffffffffffffffffffffffffffffffffffffffff1682612916565b81546114639073ffffffffffffffffffffffffffffffffffffffff1661140f876121fd565b6114bb565b61148961dead611484600461147e856001612973565b906129c7565b6128d5565b6004808301546114bb9173ffffffffffffffffffffffffffffffffffffffff9091169061140f9061147e856007612973565b85837f4a99228a8a6d774d261be57ab0ed833bb1bae1f22bbbd3d4767b75ad03fdddf7876040516114ec9190613c76565b60405180910390a3505050505050565b3360009081526001602052604090205460ff16611545576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614551565b600061155184836117ca565b6000848152600760209081526040808320848452909152902054909150156115a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614405565b600081815260086020526040902060010154156115ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614999565b60006115f942610ecd565b90506000611606846121fd565b600083815260096020908152604080832033845290915290205490915061162d90826126f3565b60008381526009602090815260408083203380855290835281842094909455805160c08101825293845242848301908152848201898152606086018581526080870186815260a088018781528b88526008909652939095209551865473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161788559251600188015590516002870155935160038601559051600490940180549251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff95909416929091169190911792909216179055611740868686612a13565b857fa57b3e1f3af9eca02201028629700658608222c365064584cfe65d9630ef4f7b856040516117709190613c76565b60405180910390a250505061178433612435565b61178d3361112e565b10156117c5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144bf565b505050565b600082826040516020016117df929190613acf565b60405160208183030381529060405280519060200120905092915050565b600a81565b6000610ffd82600a6129c7565b600c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61183f61246f565b73ffffffffffffffffffffffffffffffffffffffff811661188c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148df565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60026000541415611910576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148a8565b6002600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602081905260409091205460ff16151514611979576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061400a565b61198333826127d8565b61198d8282612916565b8173ffffffffffffffffffffffffffffffffffffffff167febedb8b3c678666e7f36970bc8f57abf6d8fa2e828c0da91ea5b75bf68ed101a826040516119d39190613c76565b60405180910390a250506001600055565b600087878787878787604051602001611a039796959493929190614a74565b604051602081830303815290604052805190602001209050979650505050505050565b6000611a64848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612bc992505050565b90506000611a7282846117ca565b90506000805b85811015611b365773ffffffffffffffffffffffffffffffffffffffff8816600090815260066020526040812081898985818110611ab257fe5b9050602002013581526020019081526020016000205490506000811115611b2d57611add83826126f3565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040812091945090818a8a86818110611b1357fe5b905060200201358152602001908152602001600020819055505b50600101611a78565b50611b41828261262c565b611b4b8782612916565b828773ffffffffffffffffffffffffffffffffffffffff167f78e830d08be9d5f957414c84d685c061ecbd8467be98b42ebb64f0118b57d2ff83604051611b929190613c76565b60405180910390a350505050505050565b7f000000000000000000000000ae78736cd615f374d3085123a210448e74fc639381565b611c0b87858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9594939250879150506124c2565b611c41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614588565b6000611c4d87876117ca565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c845290915290205490915080611cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613de0565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c8452909152812055611cf3828261262c565b611cfd8a82612916565b87898b73ffffffffffffffffffffffffffffffffffffffff167f84eb21b24c31b27a3bc67dde4a598aad06db6e9415cd66544492b9616996143c60405160405180910390a450505050505050505050565b611d5661246f565b6000611d6284846117ca565b9050611d6c6135e7565b611d768585611e45565b9050806040015160001415611db7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e85565b80518414611dc157fe5b6040810151600090611dd6906249d4006126f3565b905080421015611e12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613fad565b60208201518251600091611e269190612739565b9050611e32848261262c565b611e3c85826128d5565b50505050505050565b611e4d6135e7565b60046000611e5b85856117ca565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b611ea261246f565b6000918252600c602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b6000878152600c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611f7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614280565b6000888152600d602052604090205460ff1615611fc5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614041565b60008611611fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613c92565b81861015612039576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906149f6565b61204333876127d8565b606087878787878760405160240161206096959493929190613c23565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcc29a3060000000000000000000000000000000000000000000000000000000017905260008c8152600a90915220549091506120f090886126f3565b60008a8152600a60205260409081902091909155517f419cb55000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063419cb55090612154908490600401613c7f565b600060405180830381600087803b15801561216e57600080fd5b505af1158015612182573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a7f0a0607688c86ec1775abcdbab7b33a3a35a6c9cde677c9be880150c231cc6b0b8a8a8a896040516121ea9493929190614aba565b60405180910390a4505050505050505050565b6000610ffd61220b83611802565b83906126f3565b61221a61246f565b600f55565b6000858152600c60205260408082205490517f99178dd8000000000000000000000000000000000000000000000000000000008152879273ffffffffffffffffffffffffffffffffffffffff9092169182916399178dd891612288913391903690600401613b1a565b600060405180830381600087803b1580156122a257600080fd5b505af11580156122b6573d6000803e3d6000fd5b5050505060006122c687866117ca565b60008781526007602090815260408083208484529091529020549091501561231a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061434b565b60008411612354576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906140d5565b600086815260076020908152604080832084845282529182902086905581516080810190925260468083526123a5928892909190614b329083013960008b8152600a60205260409020549190613000565b6000898152600a6020908152604080832093909355838252600890522060018101546123d6576123d6888888612a13565b87878a7ffdfb0eefa96935b8a8c0edf528e125dc6f3934fdbbfce31b38967e8ff413dccd896040516121ea9190613c76565b600e5481565b600d6020526000908152604090205460ff1681565b600a6020526000908152604090205481565b6000610ffd61244383613046565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902054906126f3565b600b5473ffffffffffffffffffffffffffffffffffffffff1633146124c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613d4c565b565b60008082116124fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614462565b818410612536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614223565b61253f826130c4565b835114612578576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906146b1565b8460005b845181101561261f5785600116600114156125d45784818151811061259d57fe5b6020026020010151826040516020016125b7929190613acf565b604051602081830303815290604052805190602001209150612613565b818582815181106125e157fe5b60200260200101516040516020016125fa929190613acf565b6040516020818303038152906040528051906020012091505b600195861c950161257c565b5090951495945050505050565b60008281526004602052604090208054612672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e17565b600181015460009061268490846126f3565b82549091508111156126c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061484b565b6001909101555050565b6126d584613173565b6126e3836114848484612739565b8015610ec757610ec733826128d5565b600082820183811015612732576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613ebc565b9392505050565b600082821115612775576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061409e565b50900390565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409020546127ab90826126f3565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526003602052604090209190915550565b61281a73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae78736cd615f374d3085123a210448e74fc6393168330846131f5565b5050565b33600090815260066020908152604080832085845290915290205415612870576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614734565b61287a338261277b565b336000908152600660209081526040808320858452909152908190208290555182907f0c3d250c7831051e78aa6a56679e590374c7c424415ffe4aa474491def2fe705906128c9908490613c76565b60405180910390a25050565b61281a73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ae78736cd615f374d3085123a210448e74fc6393168383613298565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090205461294690826126f3565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090209190915550565b60008261298257506000610ffd565b8282028284828161298f57fe5b0414612732576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906143a8565b6000808211612a02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061418f565b818381612a0b57fe5b049392505050565b612a1b611003565b821415612a3157612a2c83826132b7565b6117c5565b6000828152600a6020526040902054612a4a90826126f3565b6000838152600a6020908152604080832093909355600c9052205473ffffffffffffffffffffffffffffffffffffffff1680612ab2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614280565b60608483604051602401612ac7929190613acf565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ffd31c5ba00000000000000000000000000000000000000000000000000000000179052517f419cb55000000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff83169063419cb55090612b90908490600401613c7f565b600060405180830381600087803b158015612baa57600080fd5b505af1158015612bbe573d6000803e3d6000fd5b505050505050505050565b600080825111612c05576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061493c565b815160011415612c2b5781600081518110612c1c57fe5b60200260200101519050610b06565b612c33613608565b5060408051610200810182527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381527f633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d60208201527f890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d818301527f3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd86060808301919091527fecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da60808301527fdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da560a08301527f617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d760c08301527f292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead60e08301527fe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e106101008301527f7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f826101208301527fe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e836365166101408301527f3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c6101608301527fad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e6101808301527fa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab6101a08301527f4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c8626101c08301527f2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf106101e0830152825183815280820184529192909190602082018180368337505085519192506000918291508180805b6001841115612fdc5750506002820460018084161460005b82811015612f58578a8160020281518110612eff57fe5b602002602001015196508a8160020260010181518110612f1b57fe5b6020026020010151955086602089015285604089015287805190602001208b8281518110612f4557fe5b6020908102919091010152600101612ee8565b508015612fbb57896001850381518110612f6e57fe5b60200260200101519550878360108110612f8457fe5b602002015160001b945085602088015284604088015286805190602001208a8381518110612fae57fe5b6020026020010181815250505b80612fc7576000612fca565b60015b60ff1682019350600190920191612ed0565b89600081518110612fe957fe5b602002602001015198505050505050505050919050565b6000818484111561303e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019190613c7f565b505050900390565b60008061305242610ecd565b9050600080613840600e548161306457fe5b04905060005b818110156130ba57808403600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a1684529091529020546130b09084906126f3565b925060010161306a565b5090949350505050565b60008082116130ff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906142b7565b816001141561311057506000610b06565b81600060805b6001811061315e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001821b01811b8316156131565791821c91908101905b60011c613116565b506001811b8414612732576001019392505050565b60008181526005602052604090205460ff16156131bc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906141c6565b600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b610ec7846323b872dd60e01b85858560405160240161321693929190613b84565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526133bf565b6117c58363a9059cbb60e01b8484604051602401613216929190613bb5565b60006132c383836117ca565b6000818152600460205260409020549091501561330c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614314565b60008211613346576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144f4565b6040805160608101825283815260006020808301828152428486019081528684526004909252918490209251835590516001830155516002909101555183907fb33d2162aead99dab59e77a7a67ea025b776bf8ca8079e132afdf9b23e03bd42906133b2908590613c76565b60405180910390a2505050565b6060613421826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166134759092919063ffffffff16565b8051909150156117c5578080602001905181019061343f9190613880565b6117c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614791565b6060613484848460008561348c565b949350505050565b6060824710156134c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614132565b6134d18561358e565b613507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061461d565b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516135319190613add565b60006040518083038185875af1925050503d806000811461356e576040519150601f19603f3d011682016040523d82523d6000602084013e613573565b606091505b5091509150613583828286613594565b979650505050505050565b3b151590565b606083156135a3575081612732565b8251156135b35782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019190613c7f565b60405180606001604052806000815260200160008152602001600081525090565b6040518061020001604052806010906020820280368337509192915050565b60008083601f840112613638578182fd5b50813567ffffffffffffffff81111561364f578182fd5b602083019150836020808302850101111561366957600080fd5b9250929050565b600060208284031215613681578081fd5b813561273281614b01565b600080600080606085870312156136a1578283fd5b84356136ac81614b01565b9350602085013567ffffffffffffffff8111156136c7578384fd5b6136d387828801613627565b9598909750949560400135949350505050565b600080604083850312156136f8578182fd5b823561370381614b01565b946020939093013593505050565b60008060008060008060008060e0898b03121561372c578384fd5b883561373781614b01565b97506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff81111561376e578384fd5b61377a8b828c01613627565b999c989b50969995989497949560c00135949350505050565b600080600080608085870312156137a8578384fd5b84356137b381614b01565b966020860135965060408601359560600135945092505050565b6000806000806000806000806000806000806101608d8f0312156137ef578384fd5b6137f98d35614b01565b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d0135935067ffffffffffffffff6101208e0135111561384f578283fd5b6138608e6101208f01358f01613627565b81945080935050506101408d013590509295989b509295989b509295989b565b600060208284031215613891578081fd5b815161273281614b23565b6000602082840312156138ad578081fd5b5035919050565b600080604083850312156138c6578182fd5b50508035926020909101359150565b6000806000606084860312156138e9578283fd5b8335925060208401359150604084013561390281614b01565b809150509250925092565b600080600060608486031215613921578081fd5b505081359360208301359350604090920135919050565b6000806040838503121561394a578182fd5b82359150602083013561395c81614b01565b809150509250929050565b600080600080600080600060e0888a031215613981578081fd5b87359650602088013561399381614b01565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600080600060e0888a0312156139d9578081fd5b8735965060208801356139eb81614b01565b955060408801359450606088013593506080880135925060a0880135613a1081614b01565b8092505060c0880135905092959891949750929550565b60008060408385031215613a39578182fd5b82359150602083013561395c81614b23565b600080600080600060a08688031215613a62578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008151808452613a9d816020860160208601614ad5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b918252602082015260400190565b60008251613aef818460208701614ad5565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff851682526040602083015282604083015282846060840137818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015290151560a082015260c00190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b901515815260200190565b90815260200190565b6000602082526127326020830184613a85565b60208082526027908201527f4c315f4252473a204d757374207472616e736665722061206e6f6e2d7a65726f60408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4c315f4252473a206368616c6c656e6765506572696f64206d7573742062652060408201527f646976697369626c652062792054494d455f534c4f545f53495a450000000000606082015260800190565b6020808252601f908201527f4c315f4252473a2043616c6c6572206973206e6f7420746865206f776e657200604082015260600190565b60208082526028908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e20626f6e646564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f4c325f4252473a207472616e73666572496420686173206e6f20626f6e640000604082015260600190565b6020808252601c908201527f4252473a205472616e7366657220726f6f74206e6f7420666f756e6400000000604082015260600190565b6020808252601e908201527f4143543a204164647265737320697320616c726561647920626f6e6465720000604082015260600190565b6020808252601b908201527f4252473a205472616e73666572526f6f74206e6f7420666f756e640000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526025908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792072657360408201527f6f6c766564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792063686160408201527f6c6c656e67656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4252473a205472616e73666572526f6f742063616e6e6f74206265207265736360408201527f756564206265666f726520746865205265736375652044656c61790000000000606082015260800190565b6020808252601a908201527f4143543a2041646472657373206973206e6f7420626f6e646572000000000000604082015260600190565b60208082526028908201527f4c315f4252473a2053656e647320746f207468697320636861696e496420617260408201527f6520706175736564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602e908201527f4c315f4252473a20726f6f74436f6d6d69747465644174206d7573742062652060408201527f67726561746572207468616e2030000000000000000000000000000000000000606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252602c908201527f4252473a20546865207472616e736665722068617320616c726561647920626560408201527f656e2077697468647261776e0000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4c69625f4d65726b6c65547265653a20496e646578206f7574206f6620626f7560408201527f6e64732e00000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f4c315f4252473a20636861696e4964206e6f7420737570706f72746564000000604082015260600190565b60208082526030908201527f4c69625f4d65726b6c65547265653a2043616e6e6f7420636f6d70757465206360408201527f65696c286c6f675f3229206f6620302e00000000000000000000000000000000606082015260800190565b6020808252601e908201527f4252473a205472616e7366657220726f6f7420616c7265616479207365740000604082015260600190565b60208082526026908201527f4c315f4252473a205472616e73666572526f6f7420616c726561647920636f6e60408201527f6669726d65640000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20636f6e6669726d65640000000000000000000000000000000000606082015260800190565b60208082526037908201527f4c69625f4d65726b6c65547265653a20546f74616c206c6561766573206d757360408201527f742062652067726561746572207468616e207a65726f2e000000000000000000606082015260800190565b6020808252818101527f4143543a204e6f7420656e6f75676820617661696c61626c6520637265646974604082015260600190565b6020808252602d908201527f4252473a2043616e6e6f7420736574205472616e73666572526f6f7420746f7460408201527f616c416d6f756e74206f66203000000000000000000000000000000000000000606082015260800190565b60208082526019908201527f4143543a2043616c6c6572206973206e6f7420626f6e64657200000000000000604082015260600190565b6020808252601b908201527f4252473a20496e76616c6964207472616e736665722070726f6f660000000000604082015260600190565b602080825260409082018190527f4c315f4252473a205472616e73666572526f6f742063616e6e6f742062652063908201527f68616c6c656e676564206166746572206368616c6c656e676520706572696f64606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526026908201527f4c315f4252473a204368616c6c656e676520706572696f6420686173206e6f7460408201527f20656e6465640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252604d908201527f4c69625f4d65726b6c65547265653a20546f74616c207369626c696e6773206460408201527f6f6573206e6f7420636f72726563746c7920636f72726573706f6e6420746f2060608201527f746f74616c206c65617665732e00000000000000000000000000000000000000608082015260a00190565b60208082526027908201527f4252473a205769746864726177616c2068617320616c7265616479206265656e60408201527f20626f6e64656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e206368616c6c656e6765640000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4252473a205769746864726177616c2065786365656473205472616e7366657260408201527f526f6f7420746f74616c00000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4c315f4252473a205f6e6577476f7665726e616e63652063616e6e6f7420626560408201527f2061646472657373283029000000000000000000000000000000000000000000606082015260800190565b60208082526034908201527f4c69625f4d65726b6c65547265653a204d7573742070726f766964652061742060408201527f6c65617374206f6e65206c65616620686173682e000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20626f6e6465640000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f4c315f4252473a2052656c61796572206665652063616e6e6f7420657863656560408201527f6420616d6f756e74000000000000000000000000000000000000000000000000606082015260800190565b81518152602080830151908201526040918201519181019190915260600190565b96875273ffffffffffffffffffffffffffffffffffffffff95909516602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b93845260208401929092526040830152606082015260800190565b60005b83811015614af0578181015183820152602001614ad8565b83811115610ec75750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114610fc857600080fd5b8015158114610fc857600080fdfe4c315f4252473a20416d6f756e74206578636565647320636861696e42616c616e63652e205468697320696e646963617465732061206c617965722d32206661696c7572652ea2646970667358221220f548b4a85c13af0cf10d4b98bc2d4014c0fb5bdcb08efee30389464c055edb0564736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ae78736cd615f374d3085123a210448e74fc63930000000000000000000000000000000000000000000000000000000000000060000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000002a6303e6b99d451df3566068ebb110708335658f
-----Decoded View---------------
Arg [0] : _l1CanonicalToken (address): 0xae78736Cd615f374D3085123A210448E74Fc6393
Arg [1] : bonders (address[]): 0x2A6303e6b99d451Df3566068EBb110708335658f
Arg [2] : _governance (address): 0xF56e305024B195383245A075737d16dBdb8487Fb
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000ae78736cd615f374d3085123a210448e74fc6393
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000002a6303e6b99d451df3566068ebb110708335658f
Loading...
Loading
Loading...
Loading
Net Worth in USD
$32,998.17
Net Worth in ETH
16.865282
Token Allocations
RETH
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $2,253.3 | 14.6444 | $32,998.17 |
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.