Latest 25 from a total of 1,605,519 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| 0x7c2b2950 | 24457331 | 4 days ago | IN | 0.0065 ETH | 0.0000011 | ||||
| Send To L2 | 24450557 | 5 days ago | IN | 0.0738212 ETH | 0.00000413 | ||||
| Send To L2 | 24418187 | 9 days ago | IN | 0.004 ETH | 0.00003502 | ||||
| Withdraw | 24410995 | 10 days ago | IN | 0 ETH | 0.0001341 | ||||
| Send To L2 | 24391350 | 13 days ago | IN | 0.01260693 ETH | 0.00018201 | ||||
| Send To L2 | 24349811 | 19 days ago | IN | 0.0047 ETH | 0.00005477 | ||||
| Send To L2 | 24322534 | 23 days ago | IN | 1.646 ETH | 0.0000048 | ||||
| Withdraw | 24322521 | 23 days ago | IN | 0 ETH | 0.00000402 | ||||
| Send To L2 | 24322457 | 23 days ago | IN | 0.0003 ETH | 0.00000391 | ||||
| Get Transfer Roo... | 24266283 | 31 days ago | IN | 0 ETH | 0.00000094 | ||||
| Transfer Root Co... | 24266281 | 31 days ago | IN | 0 ETH | 0.00000069 | ||||
| Send To L2 | 24266146 | 31 days ago | IN | 0.001 ETH | 0.00026802 | ||||
| Send To L2 | 24180742 | 43 days ago | IN | 0.381 ETH | 0.00027007 | ||||
| Withdraw | 24113494 | 52 days ago | IN | 0 ETH | 0.00000284 | ||||
| Unstake | 23969621 | 72 days ago | IN | 0 ETH | 0.00002196 | ||||
| Settle Bonded Wi... | 23941717 | 76 days ago | IN | 0 ETH | 0.0001768 | ||||
| Bond Transfer Ro... | 23941715 | 76 days ago | IN | 0 ETH | 0.00004603 | ||||
| Send To L2 | 23937352 | 77 days ago | IN | 0.004 ETH | 0.00017652 | ||||
| Send To L2 | 23937352 | 77 days ago | IN | 0.004 ETH | 0.00017652 | ||||
| Send To L2 | 23937351 | 77 days ago | IN | 0.004 ETH | 0.0001764 | ||||
| Settle Bonded Wi... | 23931282 | 77 days ago | IN | 0 ETH | 0.00003514 | ||||
| Withdraw | 23930977 | 78 days ago | IN | 0 ETH | 0.00014412 | ||||
| Settle Bonded Wi... | 23929800 | 78 days ago | IN | 0 ETH | 0.00001274 | ||||
| Settle Bonded Wi... | 23929653 | 78 days ago | IN | 0 ETH | 0.00000891 | ||||
| Settle Bonded Wi... | 23929652 | 78 days ago | IN | 0 ETH | 0.00012813 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 24410995 | 10 days ago | 10.01229465 ETH | ||||
| Transfer | 24322521 | 23 days ago | 1.64631683 ETH | ||||
| Transfer | 24113494 | 52 days ago | 8.01184165 ETH | ||||
| Send To L2 | 23971631 | 72 days ago | 0.005 ETH | ||||
| Transfer | 23969621 | 72 days ago | 247.7607589 ETH | ||||
| Send To L2 | 23956538 | 74 days ago | 0.01781223 ETH | ||||
| Send To L2 | 23956521 | 74 days ago | 0.03357549 ETH | ||||
| Transfer | 23930977 | 78 days ago | 0.03672803 ETH | ||||
| Transfer | 23921837 | 79 days ago | 0.00118541 ETH | ||||
| Transfer | 23921837 | 79 days ago | 2.3504422 ETH | ||||
| Transfer | 23901318 | 82 days ago | 0.0000918 ETH | ||||
| Transfer | 23901318 | 82 days ago | 0.00619558 ETH | ||||
| Send To L2 | 23893027 | 83 days ago | 0.1 ETH | ||||
| Send To L2 | 23892991 | 83 days ago | 0.1646 ETH | ||||
| Send To L2 | 23892990 | 83 days ago | 0.1646 ETH | ||||
| Transfer | 23867854 | 86 days ago | 0.00016006 ETH | ||||
| Transfer | 23867854 | 86 days ago | 0.00912802 ETH | ||||
| Transfer | 23858036 | 88 days ago | 0.00010391 ETH | ||||
| Transfer | 23858036 | 88 days ago | 0.00089715 ETH | ||||
| Transfer | 23844395 | 90 days ago | 0.00022673 ETH | ||||
| Transfer | 23844395 | 90 days ago | 0.00976734 ETH | ||||
| Transfer | 23837839 | 91 days ago | 0.000201 ETH | ||||
| Transfer | 23837839 | 91 days ago | 0.21005141 ETH | ||||
| Transfer | 23805835 | 95 days ago | 0.00011715 ETH | ||||
| Transfer | 23805835 | 95 days ago | 0.0047779 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
L1_ETH_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 "./L1_Bridge.sol";
/**
* @dev A L1_Bridge that uses an ETH as the canonical token
*/
contract L1_ETH_Bridge is L1_Bridge {
constructor (address[] memory bonders, address _governance) public L1_Bridge(bonders, _governance) {}
/* ========== Override Functions ========== */
function _transferFromBridge(address recipient, uint256 amount) internal override {
(bool success, ) = recipient.call{value: amount}(new bytes(0));
require(success, 'L1_ETH_BRG: ETH transfer failed');
}
function _transferToBridge(address /*from*/, uint256 amount) internal override {
require(msg.value == amount, "L1_ETH_BRG: Value does not match amount");
}
}// 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 = 10 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;
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 <0.8.0;
pragma experimental ABIEncoderV2;
interface IMessengerWrapper {
function sendCrossDomainMessage(bytes memory _calldata) external;
function verifySender(address l1BridgeCaller, bytes memory _data) external;
}// 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.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;
}
}// 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 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;
}
}{
"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":"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":"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
608060405262015180600e55620d2f00600f556103846010553480156200002557600080fd5b5060405162004af838038062004af88339810160408190526200004891620001b2565b81818180600160008190555060005b81518110156200016657600160008383815181106200007257fe5b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1615620000c25760405162461bcd60e51b8152600401620000b9906200027d565b60405180910390fd5b6001806000848481518110620000d457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055508181815181106200012057fe5b60200260200101516001600160a01b03167f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e2360405160405180910390a260010162000057565b5050600b80546001600160a01b0319166001600160a01b03939093169290921790915550620002d992505050565b80516001600160a01b0381168114620001ac57600080fd5b92915050565b60008060408385031215620001c5578182fd5b82516001600160401b0380821115620001dc578384fd5b818501915085601f830112620001f0578384fd5b815181811115620001ff578485fd5b6020915081810262000213838201620002b2565b8281528381019085850183870186018b10156200022e578889fd5b8896505b848710156200025c57620002478b8262000194565b83526001969096019591850191850162000232565b5080975050505050620002728682870162000194565b925050509250929050565b6020808252818101527f4143543a2043616e6e6f7420616464206475706c696361746520626f6e646572604082015260600190565b6040518181016001600160401b0381118282101715620002d157600080fd5b604052919050565b61480f80620002e96000396000f3fe6080604052600436106102f25760003560e01c806381707b801161018f578063cbd1642e116100e1578063eecd57e61161008a578063fa2a69a311610064578063fa2a69a314610814578063fc110b6714610834578063ffa9286c14610854576102f2565b8063eecd57e6146107bf578063ef6ebe5e146107df578063f3f480d9146107ff576102f2565b8063d5ef7551116100bb578063d5ef75511461076c578063deace8f51461078c578063e19be1501461079f576102f2565b8063cbd1642e146106ff578063ce803b4f1461071f578063d44481631461074c576102f2565b8063a35962f311610143578063af215f941161011d578063af215f941461069f578063b162717e146106bf578063c7525dd3146106df576102f2565b8063a35962f31461064c578063ab033ea91461066c578063adc9772e1461068c576102f2565b8063960a7afa11610174578063960a7afa146105f757806398c4f76d14610617578063a239f5ee1461062c576102f2565b806381707b80146105b75780638d8798bf146105d7576102f2565b80633a7af631116102485780635a7e1083116101fc5780636cff06a7116101d65780636cff06a71461056d5780637398d28214610582578063767631d5146105a2576102f2565b80635a7e1083146104f95780635aa6e6751461052b5780635d475fdd1461054d576102f2565b80634de8c6e61161022d5780634de8c6e6146104a45780635325937f146104b957806357344e6f146104d9576102f2565b80633a7af631146104575780633b8fea2814610484576102f2565b806323c452cd116102aa578063302830ab11610284578063302830ab146104025780633408e4701461042257806339ada66914610437576102f2565b806323c452cd146103a25780632b85dcc9146103c25780632e17de78146103e2576102f2565b806313948c76116102db57806313948c7614610339578063149420241461036f5780631bbe15ea1461038f576102f2565b806304e6c2c0146102f75780630f7aadb714610319575b600080fd5b34801561030357600080fd5b506103176103123660046133ac565b610874565b005b34801561032557600080fd5b50610317610334366004613509565b61095e565b34801561034557600080fd5b506103596103543660046133ac565b610abf565b6040516103669190613943565b60405180910390f35b34801561037b57600080fd5b5061031761038a366004613747565b610aeb565b61031761039d36600461362d565b610b31565b3480156103ae57600080fd5b506103176103bd3660046134cf565b610d9b565b3480156103ce57600080fd5b506103596103dd3660046135bc565b610ead565b3480156103ee57600080fd5b506103176103fd3660046135bc565b610eb5565b34801561040e57600080fd5b5061035961041d366004613422565b610fab565b34801561042e57600080fd5b50610359610fe3565b34801561044357600080fd5b506103176104523660046135bc565b610fe7565b34801561046357600080fd5b506104776104723660046135bc565b610ff4565b6040516103669190613938565b34801561049057600080fd5b5061035961049f3660046135d4565b611009565b3480156104b057600080fd5b50610359611026565b3480156104c557600080fd5b506103176104d43660046133ac565b61102c565b3480156104e557600080fd5b506103596104f43660046133ac565b61110e565b34801561050557600080fd5b506105196105143660046135bc565b611136565b604051610366969594939291906138a8565b34801561053757600080fd5b5061054061119a565b604051610366919061381d565b34801561055957600080fd5b506103176105683660046135bc565b6111b6565b34801561057957600080fd5b506103596111ff565b34801561058e57600080fd5b5061035961059d366004613658565b611205565b3480156105ae57600080fd5b50610359611222565b3480156105c357600080fd5b506103176105d236600461362d565b611228565b3480156105e357600080fd5b506103176105f236600461362d565b6114dc565b34801561060357600080fd5b506103596106123660046135d4565b6117aa565b34801561062357600080fd5b506103596117dd565b34801561063857600080fd5b506103596106473660046135bc565b6117e2565b34801561065857600080fd5b506105406106673660046135bc565b6117ef565b34801561067857600080fd5b506103176106873660046133ac565b611817565b61031761069a366004613422565b6118b3565b3480156106ab57600080fd5b506103596106ba366004613687565b6119c4565b3480156106cb57600080fd5b506103176106da3660046133c8565b611a06565b3480156106eb57600080fd5b506103176106fa36600461344d565b611b83565b34801561070b57600080fd5b5061031761071a3660046135f5565b611d0a565b34801561072b57600080fd5b5061073f61073a3660046135d4565b611e01565b60405161036691906146c3565b34801561075857600080fd5b50610317610767366004613658565b611e56565b34801561077857600080fd5b506104776107873660046133ac565b611eb1565b61031761079a3660046136df565b611edc565b3480156107ab57600080fd5b506103596107ba3660046135bc565b6121b9565b3480156107cb57600080fd5b506103176107da3660046135bc565b6121ce565b3480156107eb57600080fd5b506103176107fa36600461376f565b6121db565b34801561080b57600080fd5b506103596123c4565b34801561082057600080fd5b5061047761082f3660046135bc565b6123ca565b34801561084057600080fd5b5061035961084f3660046135bc565b6123df565b34801561086057600080fd5b5061035961086f3660046133ac565b6123f1565b61087c61242b565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602081905260409091205460ff161515146108ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613d0e565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4234ba611d325b3ba434c4e1b037967b955b1274d4185ee9847b7491111a48ff9190a250565b6002600054141561099b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614518565b600260009081556109b86109ad610fe3565b8e8e8e8e8e8e6119c4565b90506109fe81868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d95949392508891505061247e565b610a34576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061428c565b6000610a4088886117aa565b9050610a4c818e6125e8565b610a59828f8f6000612688565b8d73ffffffffffffffffffffffffffffffffffffffff16827f9475cdbde5fc71fe2ccd413c82878ee54d061b9f74f9e2e1a03ff1178821502c8f8f604051610aa29291906137f3565b60405180910390a350506001600055505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020545b919050565b610af361242b565b6000918252600d602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000610b3d84846117aa565b600081815260086020908152604080832086845260078352818420858552909252909120549192509015610b9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614109565b6001810154610bd8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613a87565b6000610bf3600e5483600101546126af90919063ffffffff16565b905042811015610c2f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906142c3565b600382015415610c6b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613c54565b4260038301556004820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556001820154600090610cae90610ead565b90506000610cbb876121b9565b8454600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9094168084529390915290205491925090610cfe90836126f5565b600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff80871685529252909120919091558554610d3f911683612737565b6000610d4a896117e2565b9050610d563382612794565b89877fec2697dcba539a0ac947cdf1f6d0b6314c065429eca8be2435859b10209d4c278b604051610d879190613943565b60405180910390a350505050505050505050565b3360009081526001602052604090205460ff16610de4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614255565b60026000541415610e21576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614518565b60026000908155610e3f610e33610fe3565b868686866000806119c4565b9050610e4b81856127d1565b610e5781868685612688565b506001600055610e66336123f1565b610e6f3361110e565b1015610ea7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141c3565b50505050565b613840900490565b60026000541415610ef2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614518565b6002600055610f013382612737565b610f0b3382612888565b3373ffffffffffffffffffffffffffffffffffffffff167f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd82604051610f519190613943565b60405180910390a26001600055610f67336123f1565b610f703361110e565b1015610fa8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141c3565b50565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602090815260408083208484529091529020545b92915050565b4690565b610fef61242b565b601055565b60009081526005602052604090205460ff1690565b600760209081526000928352604080842090915290825290205481565b61384081565b61103461242b565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff1615611094576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613b52565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909217909155517f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e239190a250565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b6008602052600090815260409020805460018201546002830154600384015460049094015473ffffffffffffffffffffffffffffffffffffffff93841694929391929181169074010000000000000000000000000000000000000000900460ff1686565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b6111be61242b565b6138408106156111fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906139f3565b600e55565b60105481565b600960209081526000928352604080842090915290825290205481565b600f5481565b600061123484846117aa565b6000818152600860205260409020600381015491925090611281576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061445e565b600f546003820154611292916126af565b42116112ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614321565b600481015474010000000000000000000000000000000000000000900460ff1615611321576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613bf7565b6004810180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055600061136d856117e2565b6000858152600760209081526040808320878452909152902054909150156114485760105460008581526007602090815260408083208784529091529020546113b5916126af565b826001015411156113f95781546113f49073ffffffffffffffffffffffffffffffffffffffff166113ef836113e9896121b9565b906126af565b61293c565b611443565b600482015461141e9073ffffffffffffffffffffffffffffffffffffffff168261293c565b81546114439073ffffffffffffffffffffffffffffffffffffffff166113ef876121b9565b61149b565b61146961dead611464600461145e856001612999565b906129ed565b612888565b60048083015461149b9173ffffffffffffffffffffffffffffffffffffffff909116906113ef9061145e856007612999565b85837f4a99228a8a6d774d261be57ab0ed833bb1bae1f22bbbd3d4767b75ad03fdddf7876040516114cc9190613943565b60405180910390a3505050505050565b3360009081526001602052604090205460ff16611525576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614255565b600061153184836117aa565b600084815260076020908152604080832084845290915290205490915015611585576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614109565b600081815260086020526040902060010154156115ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614609565b60006115d942610ead565b905060006115e6846121b9565b600083815260096020908152604080832033845290915290205490915061160d90826126af565b60008381526009602090815260408083203380855290835281842094909455805160c08101825293845242848301908152848201898152606086018581526080870186815260a088018781528b88526008909652939095209551865473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161788559251600188015590516002870155935160038601559051600490940180549251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff95909416929091169190911792909216179055611720868686612a39565b857fa57b3e1f3af9eca02201028629700658608222c365064584cfe65d9630ef4f7b856040516117509190613943565b60405180910390a2505050611764336123f1565b61176d3361110e565b10156117a5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141c3565b505050565b600082826040516020016117bf9291906137f3565b60405160208183030381529060405280519060200120905092915050565b600a81565b6000610fdd82600a6129ed565b600c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61181f61242b565b73ffffffffffffffffffffffffffffffffffffffff811661186c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061454f565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600260005414156118f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614518565b6002600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602081905260409091205460ff16151514611959576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613d0e565b6119633382612794565b61196d828261293c565b8173ffffffffffffffffffffffffffffffffffffffff167febedb8b3c678666e7f36970bc8f57abf6d8fa2e828c0da91ea5b75bf68ed101a826040516119b39190613943565b60405180910390a250506001600055565b6000878787878787876040516020016119e397969594939291906146e4565b604051602081830303815290604052805190602001209050979650505050505050565b6000611a44848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612bef92505050565b90506000611a5282846117aa565b90506000805b85811015611b165773ffffffffffffffffffffffffffffffffffffffff8816600090815260066020526040812081898985818110611a9257fe5b9050602002013581526020019081526020016000205490506000811115611b0d57611abd83826126af565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040812091945090818a8a86818110611af357fe5b905060200201358152602001908152602001600020819055505b50600101611a58565b50611b2182826125e8565b611b2b878261293c565b828773ffffffffffffffffffffffffffffffffffffffff167f78e830d08be9d5f957414c84d685c061ecbd8467be98b42ebb64f0118b57d2ff83604051611b729190613943565b60405180910390a350505050505050565b611bc787858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c95949392508791505061247e565b611bfd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061428c565b6000611c0987876117aa565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c845290915290205490915080611c74576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613ae4565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c8452909152812055611caf82826125e8565b611cb98a8261293c565b87898b73ffffffffffffffffffffffffffffffffffffffff167f84eb21b24c31b27a3bc67dde4a598aad06db6e9415cd66544492b9616996143c60405160405180910390a450505050505050505050565b611d1261242b565b6000611d1e84846117aa565b9050611d28613323565b611d328585611e01565b9050806040015160001415611d73576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613b89565b80518414611d7d57fe5b6040810151600090611d92906249d4006126af565b905080421015611dce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613cb1565b60208201518251600091611de291906126f5565b9050611dee84826125e8565b611df88582612888565b50505050505050565b611e09613323565b60046000611e1785856117aa565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b611e5e61242b565b6000918252600c602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b6000878152600c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611f38576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613f84565b6000888152600d602052604090205460ff1615611f81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613d45565b60008611611fbb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061395f565b81861015611ff5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614666565b611fff3387612794565b606087878787878760405160240161201c969594939291906138f0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcc29a3060000000000000000000000000000000000000000000000000000000017905260008c8152600a90915220549091506120ac90886126af565b60008a8152600a60205260409081902091909155517f419cb55000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063419cb5509061211090849060040161394c565b600060405180830381600087803b15801561212a57600080fd5b505af115801561213e573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a7f0a0607688c86ec1775abcdbab7b33a3a35a6c9cde677c9be880150c231cc6b0b8a8a8a896040516121a6949392919061472a565b60405180910390a4505050505050505050565b6000610fdd6121c7836117e2565b83906126af565b6121d661242b565b600f55565b6000858152600c60205260408082205490517f99178dd8000000000000000000000000000000000000000000000000000000008152879273ffffffffffffffffffffffffffffffffffffffff9092169182916399178dd89161224491339190369060040161383e565b600060405180830381600087803b15801561225e57600080fd5b505af1158015612272573d6000803e3d6000fd5b50505050600061228287866117aa565b6000878152600760209081526040808320848452909152902054909150156122d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061404f565b60008411612310576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613dd9565b600086815260076020908152604080832084845282529182902086905581516080810190925260468083526123619288929091906147949083013960008b8152600a60205260409020549190613026565b6000898152600a60209081526040808320939093558382526008905220600181015461239257612392888888612a39565b87878a7ffdfb0eefa96935b8a8c0edf528e125dc6f3934fdbbfce31b38967e8ff413dccd896040516121a69190613943565b600e5481565b600d6020526000908152604090205460ff1681565b600a6020526000908152604090205481565b6000610fdd6123ff8361306c565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902054906126af565b600b5473ffffffffffffffffffffffffffffffffffffffff16331461247c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613a50565b565b60008082116124b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614166565b8184106124f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613f27565b6124fb826130ea565b835114612534576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061437e565b8460005b84518110156125db5785600116600114156125905784818151811061255957fe5b6020026020010151826040516020016125739291906137f3565b6040516020818303038152906040528051906020012091506125cf565b8185828151811061259d57fe5b60200260200101516040516020016125b69291906137f3565b6040516020818303038152906040528051906020012091505b600195861c9501612538565b5090951495945050505050565b6000828152600460205260409020805461262e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613b1b565b600181015460009061264090846126af565b825490915081111561267e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906144bb565b6001909101555050565b61269184613199565b61269f8361146484846126f5565b8015610ea757610ea73382612888565b6000828201838110156126ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613bc0565b9392505050565b600082821115612731576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613da2565b50900390565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205461276790826126af565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526003602052604090209190915550565b8034146127cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613eca565b5050565b33600090815260066020908152604080832085845290915290205415612823576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614401565b61282d3382612737565b336000908152600660209081526040808320858452909152908190208290555182907f0c3d250c7831051e78aa6a56679e590374c7c424415ffe4aa474491def2fe7059061287c908490613943565b60405180910390a25050565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516128bf9190613801565b60006040518083038185875af1925050503d80600081146128fc576040519150601f19603f3d011682016040523d82523d6000602084013e612901565b606091505b50509050806117a5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906139bc565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090205461296c90826126af565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090209190915550565b6000826129a857506000610fdd565b828202828482816129b557fe5b04146126ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906140ac565b6000808211612a28576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613e36565b818381612a3157fe5b049392505050565b612a41610fe3565b821415612a5757612a52838261321b565b6117a5565b6000828152600a6020526040902054612a7090826126af565b6000838152600a6020908152604080832093909355600c9052205473ffffffffffffffffffffffffffffffffffffffff1680612ad8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613f84565b60608483604051602401612aed9291906137f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ffd31c5ba00000000000000000000000000000000000000000000000000000000179052517f419cb55000000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff83169063419cb55090612bb690849060040161394c565b600060405180830381600087803b158015612bd057600080fd5b505af1158015612be4573d6000803e3d6000fd5b505050505050505050565b600080825111612c2b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906145ac565b815160011415612c515781600081518110612c4257fe5b60200260200101519050610ae6565b612c59613344565b5060408051610200810182527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381527f633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d60208201527f890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d818301527f3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd86060808301919091527fecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da60808301527fdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da560a08301527f617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d760c08301527f292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead60e08301527fe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e106101008301527f7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f826101208301527fe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e836365166101408301527f3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c6101608301527fad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e6101808301527fa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab6101a08301527f4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c8626101c08301527f2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf106101e0830152825183815280820184529192909190602082018180368337505085519192506000918291508180805b60018411156130025750506002820460018084161460005b82811015612f7e578a8160020281518110612f2557fe5b602002602001015196508a8160020260010181518110612f4157fe5b6020026020010151955086602089015285604089015287805190602001208b8281518110612f6b57fe5b6020908102919091010152600101612f0e565b508015612fe157896001850381518110612f9457fe5b60200260200101519550878360108110612faa57fe5b602002015160001b945085602088015284604088015286805190602001208a8381518110612fd457fe5b6020026020010181815250505b80612fed576000612ff0565b60015b60ff1682019350600190920191612ef6565b8960008151811061300f57fe5b602002602001015198505050505050505050919050565b60008184841115613064576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1919061394c565b505050900390565b60008061307842610ead565b9050600080613840600e548161308a57fe5b04905060005b818110156130e057808403600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a1684529091529020546130d69084906126af565b9250600101613090565b5090949350505050565b6000808211613125576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613fbb565b816001141561313657506000610ae6565b81600060805b60018110613184577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001821b01811b83161561317c5791821c91908101905b60011c61313c565b506001811b84146126ee576001019392505050565b60008181526005602052604090205460ff16156131e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613e6d565b600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600061322783836117aa565b60008181526004602052604090205490915015613270576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614018565b600082116132aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141f8565b6040805160608101825283815260006020808301828152428486019081528684526004909252918490209251835590516001830155516002909101555183907fb33d2162aead99dab59e77a7a67ea025b776bf8ca8079e132afdf9b23e03bd4290613316908590613943565b60405180910390a2505050565b60405180606001604052806000815260200160008152602001600081525090565b6040518061020001604052806010906020820280368337509192915050565b60008083601f840112613374578182fd5b50813567ffffffffffffffff81111561338b578182fd5b60208301915083602080830285010111156133a557600080fd5b9250929050565b6000602082840312156133bd578081fd5b81356126ee81614771565b600080600080606085870312156133dd578283fd5b84356133e881614771565b9350602085013567ffffffffffffffff811115613403578384fd5b61340f87828801613363565b9598909750949560400135949350505050565b60008060408385031215613434578182fd5b823561343f81614771565b946020939093013593505050565b60008060008060008060008060e0898b031215613468578384fd5b883561347381614771565b97506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff8111156134aa578384fd5b6134b68b828c01613363565b999c989b50969995989497949560c00135949350505050565b600080600080608085870312156134e4578384fd5b84356134ef81614771565b966020860135965060408601359560600135945092505050565b6000806000806000806000806000806000806101608d8f03121561352b578384fd5b6135358d35614771565b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d0135935067ffffffffffffffff6101208e0135111561358b578283fd5b61359c8e6101208f01358f01613363565b81945080935050506101408d013590509295989b509295989b509295989b565b6000602082840312156135cd578081fd5b5035919050565b600080604083850312156135e6578182fd5b50508035926020909101359150565b600080600060608486031215613609578283fd5b8335925060208401359150604084013561362281614771565b809150509250925092565b600080600060608486031215613641578081fd5b505081359360208301359350604090920135919050565b6000806040838503121561366a578182fd5b82359150602083013561367c81614771565b809150509250929050565b600080600080600080600060e0888a0312156136a1578081fd5b8735965060208801356136b381614771565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600080600060e0888a0312156136f9578081fd5b87359650602088013561370b81614771565b955060408801359450606088013593506080880135925060a088013561373081614771565b8092505060c0880135905092959891949750929550565b60008060408385031215613759578182fd5b823591506020830135801515811461367c578182fd5b600080600080600060a08688031215613786578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b600081518084526137c1816020860160208601614745565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b918252602082015260400190565b60008251613813818460208701614745565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff851682526040602083015282604083015282846060840137818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015290151560a082015260c00190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b901515815260200190565b90815260200190565b6000602082526126ee60208301846137a9565b60208082526027908201527f4c315f4252473a204d757374207472616e736665722061206e6f6e2d7a65726f60408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f4c315f4554485f4252473a20455448207472616e73666572206661696c656400604082015260600190565b6020808252603b908201527f4c315f4252473a206368616c6c656e6765506572696f64206d7573742062652060408201527f646976697369626c652062792054494d455f534c4f545f53495a450000000000606082015260800190565b6020808252601f908201527f4c315f4252473a2043616c6c6572206973206e6f7420746865206f776e657200604082015260600190565b60208082526028908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e20626f6e646564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f4c325f4252473a207472616e73666572496420686173206e6f20626f6e640000604082015260600190565b6020808252601c908201527f4252473a205472616e7366657220726f6f74206e6f7420666f756e6400000000604082015260600190565b6020808252601e908201527f4143543a204164647265737320697320616c726561647920626f6e6465720000604082015260600190565b6020808252601b908201527f4252473a205472616e73666572526f6f74206e6f7420666f756e640000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526025908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792072657360408201527f6f6c766564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792063686160408201527f6c6c656e67656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4252473a205472616e73666572526f6f742063616e6e6f74206265207265736360408201527f756564206265666f726520746865205265736375652044656c61790000000000606082015260800190565b6020808252601a908201527f4143543a2041646472657373206973206e6f7420626f6e646572000000000000604082015260600190565b60208082526028908201527f4c315f4252473a2053656e647320746f207468697320636861696e496420617260408201527f6520706175736564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602e908201527f4c315f4252473a20726f6f74436f6d6d69747465644174206d7573742062652060408201527f67726561746572207468616e2030000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252602c908201527f4252473a20546865207472616e736665722068617320616c726561647920626560408201527f656e2077697468647261776e0000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4554485f4252473a2056616c756520646f6573206e6f74206d6174636860408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4c69625f4d65726b6c65547265653a20496e646578206f7574206f6620626f7560408201527f6e64732e00000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f4c315f4252473a20636861696e4964206e6f7420737570706f72746564000000604082015260600190565b60208082526030908201527f4c69625f4d65726b6c65547265653a2043616e6e6f7420636f6d70757465206360408201527f65696c286c6f675f3229206f6620302e00000000000000000000000000000000606082015260800190565b6020808252601e908201527f4252473a205472616e7366657220726f6f7420616c7265616479207365740000604082015260600190565b60208082526026908201527f4c315f4252473a205472616e73666572526f6f7420616c726561647920636f6e60408201527f6669726d65640000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20636f6e6669726d65640000000000000000000000000000000000606082015260800190565b60208082526037908201527f4c69625f4d65726b6c65547265653a20546f74616c206c6561766573206d757360408201527f742062652067726561746572207468616e207a65726f2e000000000000000000606082015260800190565b6020808252818101527f4143543a204e6f7420656e6f75676820617661696c61626c6520637265646974604082015260600190565b6020808252602d908201527f4252473a2043616e6e6f7420736574205472616e73666572526f6f7420746f7460408201527f616c416d6f756e74206f66203000000000000000000000000000000000000000606082015260800190565b60208082526019908201527f4143543a2043616c6c6572206973206e6f7420626f6e64657200000000000000604082015260600190565b6020808252601b908201527f4252473a20496e76616c6964207472616e736665722070726f6f660000000000604082015260600190565b602080825260409082018190527f4c315f4252473a205472616e73666572526f6f742063616e6e6f742062652063908201527f68616c6c656e676564206166746572206368616c6c656e676520706572696f64606082015260800190565b60208082526026908201527f4c315f4252473a204368616c6c656e676520706572696f6420686173206e6f7460408201527f20656e6465640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252604d908201527f4c69625f4d65726b6c65547265653a20546f74616c207369626c696e6773206460408201527f6f6573206e6f7420636f72726563746c7920636f72726573706f6e6420746f2060608201527f746f74616c206c65617665732e00000000000000000000000000000000000000608082015260a00190565b60208082526027908201527f4252473a205769746864726177616c2068617320616c7265616479206265656e60408201527f20626f6e64656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e206368616c6c656e6765640000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4252473a205769746864726177616c2065786365656473205472616e7366657260408201527f526f6f7420746f74616c00000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4c315f4252473a205f6e6577476f7665726e616e63652063616e6e6f7420626560408201527f2061646472657373283029000000000000000000000000000000000000000000606082015260800190565b60208082526034908201527f4c69625f4d65726b6c65547265653a204d7573742070726f766964652061742060408201527f6c65617374206f6e65206c65616620686173682e000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20626f6e6465640000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f4c315f4252473a2052656c61796572206665652063616e6e6f7420657863656560408201527f6420616d6f756e74000000000000000000000000000000000000000000000000606082015260800190565b81518152602080830151908201526040918201519181019190915260600190565b96875273ffffffffffffffffffffffffffffffffffffffff95909516602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b93845260208401929092526040830152606082015260800190565b60005b83811015614760578181015183820152602001614748565b83811115610ea75750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114610fa857600080fdfe4c315f4252473a20416d6f756e74206578636565647320636861696e42616c616e63652e205468697320696e646963617465732061206c617965722d32206661696c7572652ea2646970667358221220059efbacfa8e4391e713a70ec9b5c2c2563c7f47558e9ce3c7e1c29a5888cbe664736f6c634300060c00330000000000000000000000000000000000000000000000000000000000000040000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb00000000000000000000000000000000000000000000000000000000000000020000000000000000000000002a6303e6b99d451df3566068ebb110708335658f0000000000000000000000009137a628546e2b1bc26f60a5d1262fb6d58ea44a
Deployed Bytecode
0x6080604052600436106102f25760003560e01c806381707b801161018f578063cbd1642e116100e1578063eecd57e61161008a578063fa2a69a311610064578063fa2a69a314610814578063fc110b6714610834578063ffa9286c14610854576102f2565b8063eecd57e6146107bf578063ef6ebe5e146107df578063f3f480d9146107ff576102f2565b8063d5ef7551116100bb578063d5ef75511461076c578063deace8f51461078c578063e19be1501461079f576102f2565b8063cbd1642e146106ff578063ce803b4f1461071f578063d44481631461074c576102f2565b8063a35962f311610143578063af215f941161011d578063af215f941461069f578063b162717e146106bf578063c7525dd3146106df576102f2565b8063a35962f31461064c578063ab033ea91461066c578063adc9772e1461068c576102f2565b8063960a7afa11610174578063960a7afa146105f757806398c4f76d14610617578063a239f5ee1461062c576102f2565b806381707b80146105b75780638d8798bf146105d7576102f2565b80633a7af631116102485780635a7e1083116101fc5780636cff06a7116101d65780636cff06a71461056d5780637398d28214610582578063767631d5146105a2576102f2565b80635a7e1083146104f95780635aa6e6751461052b5780635d475fdd1461054d576102f2565b80634de8c6e61161022d5780634de8c6e6146104a45780635325937f146104b957806357344e6f146104d9576102f2565b80633a7af631146104575780633b8fea2814610484576102f2565b806323c452cd116102aa578063302830ab11610284578063302830ab146104025780633408e4701461042257806339ada66914610437576102f2565b806323c452cd146103a25780632b85dcc9146103c25780632e17de78146103e2576102f2565b806313948c76116102db57806313948c7614610339578063149420241461036f5780631bbe15ea1461038f576102f2565b806304e6c2c0146102f75780630f7aadb714610319575b600080fd5b34801561030357600080fd5b506103176103123660046133ac565b610874565b005b34801561032557600080fd5b50610317610334366004613509565b61095e565b34801561034557600080fd5b506103596103543660046133ac565b610abf565b6040516103669190613943565b60405180910390f35b34801561037b57600080fd5b5061031761038a366004613747565b610aeb565b61031761039d36600461362d565b610b31565b3480156103ae57600080fd5b506103176103bd3660046134cf565b610d9b565b3480156103ce57600080fd5b506103596103dd3660046135bc565b610ead565b3480156103ee57600080fd5b506103176103fd3660046135bc565b610eb5565b34801561040e57600080fd5b5061035961041d366004613422565b610fab565b34801561042e57600080fd5b50610359610fe3565b34801561044357600080fd5b506103176104523660046135bc565b610fe7565b34801561046357600080fd5b506104776104723660046135bc565b610ff4565b6040516103669190613938565b34801561049057600080fd5b5061035961049f3660046135d4565b611009565b3480156104b057600080fd5b50610359611026565b3480156104c557600080fd5b506103176104d43660046133ac565b61102c565b3480156104e557600080fd5b506103596104f43660046133ac565b61110e565b34801561050557600080fd5b506105196105143660046135bc565b611136565b604051610366969594939291906138a8565b34801561053757600080fd5b5061054061119a565b604051610366919061381d565b34801561055957600080fd5b506103176105683660046135bc565b6111b6565b34801561057957600080fd5b506103596111ff565b34801561058e57600080fd5b5061035961059d366004613658565b611205565b3480156105ae57600080fd5b50610359611222565b3480156105c357600080fd5b506103176105d236600461362d565b611228565b3480156105e357600080fd5b506103176105f236600461362d565b6114dc565b34801561060357600080fd5b506103596106123660046135d4565b6117aa565b34801561062357600080fd5b506103596117dd565b34801561063857600080fd5b506103596106473660046135bc565b6117e2565b34801561065857600080fd5b506105406106673660046135bc565b6117ef565b34801561067857600080fd5b506103176106873660046133ac565b611817565b61031761069a366004613422565b6118b3565b3480156106ab57600080fd5b506103596106ba366004613687565b6119c4565b3480156106cb57600080fd5b506103176106da3660046133c8565b611a06565b3480156106eb57600080fd5b506103176106fa36600461344d565b611b83565b34801561070b57600080fd5b5061031761071a3660046135f5565b611d0a565b34801561072b57600080fd5b5061073f61073a3660046135d4565b611e01565b60405161036691906146c3565b34801561075857600080fd5b50610317610767366004613658565b611e56565b34801561077857600080fd5b506104776107873660046133ac565b611eb1565b61031761079a3660046136df565b611edc565b3480156107ab57600080fd5b506103596107ba3660046135bc565b6121b9565b3480156107cb57600080fd5b506103176107da3660046135bc565b6121ce565b3480156107eb57600080fd5b506103176107fa36600461376f565b6121db565b34801561080b57600080fd5b506103596123c4565b34801561082057600080fd5b5061047761082f3660046135bc565b6123ca565b34801561084057600080fd5b5061035961084f3660046135bc565b6123df565b34801561086057600080fd5b5061035961086f3660046133ac565b6123f1565b61087c61242b565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602081905260409091205460ff161515146108ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613d0e565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4234ba611d325b3ba434c4e1b037967b955b1274d4185ee9847b7491111a48ff9190a250565b6002600054141561099b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614518565b600260009081556109b86109ad610fe3565b8e8e8e8e8e8e6119c4565b90506109fe81868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d95949392508891505061247e565b610a34576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061428c565b6000610a4088886117aa565b9050610a4c818e6125e8565b610a59828f8f6000612688565b8d73ffffffffffffffffffffffffffffffffffffffff16827f9475cdbde5fc71fe2ccd413c82878ee54d061b9f74f9e2e1a03ff1178821502c8f8f604051610aa29291906137f3565b60405180910390a350506001600055505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020545b919050565b610af361242b565b6000918252600d602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000610b3d84846117aa565b600081815260086020908152604080832086845260078352818420858552909252909120549192509015610b9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614109565b6001810154610bd8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613a87565b6000610bf3600e5483600101546126af90919063ffffffff16565b905042811015610c2f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906142c3565b600382015415610c6b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613c54565b4260038301556004820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556001820154600090610cae90610ead565b90506000610cbb876121b9565b8454600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9094168084529390915290205491925090610cfe90836126f5565b600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff80871685529252909120919091558554610d3f911683612737565b6000610d4a896117e2565b9050610d563382612794565b89877fec2697dcba539a0ac947cdf1f6d0b6314c065429eca8be2435859b10209d4c278b604051610d879190613943565b60405180910390a350505050505050505050565b3360009081526001602052604090205460ff16610de4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614255565b60026000541415610e21576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614518565b60026000908155610e3f610e33610fe3565b868686866000806119c4565b9050610e4b81856127d1565b610e5781868685612688565b506001600055610e66336123f1565b610e6f3361110e565b1015610ea7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141c3565b50505050565b613840900490565b60026000541415610ef2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614518565b6002600055610f013382612737565b610f0b3382612888565b3373ffffffffffffffffffffffffffffffffffffffff167f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd82604051610f519190613943565b60405180910390a26001600055610f67336123f1565b610f703361110e565b1015610fa8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141c3565b50565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602090815260408083208484529091529020545b92915050565b4690565b610fef61242b565b601055565b60009081526005602052604090205460ff1690565b600760209081526000928352604080842090915290825290205481565b61384081565b61103461242b565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff1615611094576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613b52565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909217909155517f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e239190a250565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b6008602052600090815260409020805460018201546002830154600384015460049094015473ffffffffffffffffffffffffffffffffffffffff93841694929391929181169074010000000000000000000000000000000000000000900460ff1686565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b6111be61242b565b6138408106156111fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906139f3565b600e55565b60105481565b600960209081526000928352604080842090915290825290205481565b600f5481565b600061123484846117aa565b6000818152600860205260409020600381015491925090611281576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061445e565b600f546003820154611292916126af565b42116112ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614321565b600481015474010000000000000000000000000000000000000000900460ff1615611321576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613bf7565b6004810180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055600061136d856117e2565b6000858152600760209081526040808320878452909152902054909150156114485760105460008581526007602090815260408083208784529091529020546113b5916126af565b826001015411156113f95781546113f49073ffffffffffffffffffffffffffffffffffffffff166113ef836113e9896121b9565b906126af565b61293c565b611443565b600482015461141e9073ffffffffffffffffffffffffffffffffffffffff168261293c565b81546114439073ffffffffffffffffffffffffffffffffffffffff166113ef876121b9565b61149b565b61146961dead611464600461145e856001612999565b906129ed565b612888565b60048083015461149b9173ffffffffffffffffffffffffffffffffffffffff909116906113ef9061145e856007612999565b85837f4a99228a8a6d774d261be57ab0ed833bb1bae1f22bbbd3d4767b75ad03fdddf7876040516114cc9190613943565b60405180910390a3505050505050565b3360009081526001602052604090205460ff16611525576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614255565b600061153184836117aa565b600084815260076020908152604080832084845290915290205490915015611585576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614109565b600081815260086020526040902060010154156115ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614609565b60006115d942610ead565b905060006115e6846121b9565b600083815260096020908152604080832033845290915290205490915061160d90826126af565b60008381526009602090815260408083203380855290835281842094909455805160c08101825293845242848301908152848201898152606086018581526080870186815260a088018781528b88526008909652939095209551865473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161788559251600188015590516002870155935160038601559051600490940180549251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff95909416929091169190911792909216179055611720868686612a39565b857fa57b3e1f3af9eca02201028629700658608222c365064584cfe65d9630ef4f7b856040516117509190613943565b60405180910390a2505050611764336123f1565b61176d3361110e565b10156117a5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141c3565b505050565b600082826040516020016117bf9291906137f3565b60405160208183030381529060405280519060200120905092915050565b600a81565b6000610fdd82600a6129ed565b600c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61181f61242b565b73ffffffffffffffffffffffffffffffffffffffff811661186c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061454f565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600260005414156118f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614518565b6002600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602081905260409091205460ff16151514611959576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613d0e565b6119633382612794565b61196d828261293c565b8173ffffffffffffffffffffffffffffffffffffffff167febedb8b3c678666e7f36970bc8f57abf6d8fa2e828c0da91ea5b75bf68ed101a826040516119b39190613943565b60405180910390a250506001600055565b6000878787878787876040516020016119e397969594939291906146e4565b604051602081830303815290604052805190602001209050979650505050505050565b6000611a44848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612bef92505050565b90506000611a5282846117aa565b90506000805b85811015611b165773ffffffffffffffffffffffffffffffffffffffff8816600090815260066020526040812081898985818110611a9257fe5b9050602002013581526020019081526020016000205490506000811115611b0d57611abd83826126af565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040812091945090818a8a86818110611af357fe5b905060200201358152602001908152602001600020819055505b50600101611a58565b50611b2182826125e8565b611b2b878261293c565b828773ffffffffffffffffffffffffffffffffffffffff167f78e830d08be9d5f957414c84d685c061ecbd8467be98b42ebb64f0118b57d2ff83604051611b729190613943565b60405180910390a350505050505050565b611bc787858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c95949392508791505061247e565b611bfd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061428c565b6000611c0987876117aa565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c845290915290205490915080611c74576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613ae4565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c8452909152812055611caf82826125e8565b611cb98a8261293c565b87898b73ffffffffffffffffffffffffffffffffffffffff167f84eb21b24c31b27a3bc67dde4a598aad06db6e9415cd66544492b9616996143c60405160405180910390a450505050505050505050565b611d1261242b565b6000611d1e84846117aa565b9050611d28613323565b611d328585611e01565b9050806040015160001415611d73576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613b89565b80518414611d7d57fe5b6040810151600090611d92906249d4006126af565b905080421015611dce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613cb1565b60208201518251600091611de291906126f5565b9050611dee84826125e8565b611df88582612888565b50505050505050565b611e09613323565b60046000611e1785856117aa565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b611e5e61242b565b6000918252600c602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b6000878152600c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611f38576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613f84565b6000888152600d602052604090205460ff1615611f81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613d45565b60008611611fbb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061395f565b81861015611ff5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614666565b611fff3387612794565b606087878787878760405160240161201c969594939291906138f0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcc29a3060000000000000000000000000000000000000000000000000000000017905260008c8152600a90915220549091506120ac90886126af565b60008a8152600a60205260409081902091909155517f419cb55000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063419cb5509061211090849060040161394c565b600060405180830381600087803b15801561212a57600080fd5b505af115801561213e573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a7f0a0607688c86ec1775abcdbab7b33a3a35a6c9cde677c9be880150c231cc6b0b8a8a8a896040516121a6949392919061472a565b60405180910390a4505050505050505050565b6000610fdd6121c7836117e2565b83906126af565b6121d661242b565b600f55565b6000858152600c60205260408082205490517f99178dd8000000000000000000000000000000000000000000000000000000008152879273ffffffffffffffffffffffffffffffffffffffff9092169182916399178dd89161224491339190369060040161383e565b600060405180830381600087803b15801561225e57600080fd5b505af1158015612272573d6000803e3d6000fd5b50505050600061228287866117aa565b6000878152600760209081526040808320848452909152902054909150156122d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061404f565b60008411612310576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613dd9565b600086815260076020908152604080832084845282529182902086905581516080810190925260468083526123619288929091906147949083013960008b8152600a60205260409020549190613026565b6000898152600a60209081526040808320939093558382526008905220600181015461239257612392888888612a39565b87878a7ffdfb0eefa96935b8a8c0edf528e125dc6f3934fdbbfce31b38967e8ff413dccd896040516121a69190613943565b600e5481565b600d6020526000908152604090205460ff1681565b600a6020526000908152604090205481565b6000610fdd6123ff8361306c565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902054906126af565b600b5473ffffffffffffffffffffffffffffffffffffffff16331461247c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613a50565b565b60008082116124b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614166565b8184106124f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613f27565b6124fb826130ea565b835114612534576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e19061437e565b8460005b84518110156125db5785600116600114156125905784818151811061255957fe5b6020026020010151826040516020016125739291906137f3565b6040516020818303038152906040528051906020012091506125cf565b8185828151811061259d57fe5b60200260200101516040516020016125b69291906137f3565b6040516020818303038152906040528051906020012091505b600195861c9501612538565b5090951495945050505050565b6000828152600460205260409020805461262e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613b1b565b600181015460009061264090846126af565b825490915081111561267e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906144bb565b6001909101555050565b61269184613199565b61269f8361146484846126f5565b8015610ea757610ea73382612888565b6000828201838110156126ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613bc0565b9392505050565b600082821115612731576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613da2565b50900390565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205461276790826126af565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526003602052604090209190915550565b8034146127cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613eca565b5050565b33600090815260066020908152604080832085845290915290205415612823576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614401565b61282d3382612737565b336000908152600660209081526040808320858452909152908190208290555182907f0c3d250c7831051e78aa6a56679e590374c7c424415ffe4aa474491def2fe7059061287c908490613943565b60405180910390a25050565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff84169083906040516128bf9190613801565b60006040518083038185875af1925050503d80600081146128fc576040519150601f19603f3d011682016040523d82523d6000602084013e612901565b606091505b50509050806117a5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906139bc565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090205461296c90826126af565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090209190915550565b6000826129a857506000610fdd565b828202828482816129b557fe5b04146126ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906140ac565b6000808211612a28576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613e36565b818381612a3157fe5b049392505050565b612a41610fe3565b821415612a5757612a52838261321b565b6117a5565b6000828152600a6020526040902054612a7090826126af565b6000838152600a6020908152604080832093909355600c9052205473ffffffffffffffffffffffffffffffffffffffff1680612ad8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613f84565b60608483604051602401612aed9291906137f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ffd31c5ba00000000000000000000000000000000000000000000000000000000179052517f419cb55000000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff83169063419cb55090612bb690849060040161394c565b600060405180830381600087803b158015612bd057600080fd5b505af1158015612be4573d6000803e3d6000fd5b505050505050505050565b600080825111612c2b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906145ac565b815160011415612c515781600081518110612c4257fe5b60200260200101519050610ae6565b612c59613344565b5060408051610200810182527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381527f633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d60208201527f890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d818301527f3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd86060808301919091527fecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da60808301527fdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da560a08301527f617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d760c08301527f292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead60e08301527fe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e106101008301527f7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f826101208301527fe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e836365166101408301527f3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c6101608301527fad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e6101808301527fa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab6101a08301527f4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c8626101c08301527f2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf106101e0830152825183815280820184529192909190602082018180368337505085519192506000918291508180805b60018411156130025750506002820460018084161460005b82811015612f7e578a8160020281518110612f2557fe5b602002602001015196508a8160020260010181518110612f4157fe5b6020026020010151955086602089015285604089015287805190602001208b8281518110612f6b57fe5b6020908102919091010152600101612f0e565b508015612fe157896001850381518110612f9457fe5b60200260200101519550878360108110612faa57fe5b602002015160001b945085602088015284604088015286805190602001208a8381518110612fd457fe5b6020026020010181815250505b80612fed576000612ff0565b60015b60ff1682019350600190920191612ef6565b8960008151811061300f57fe5b602002602001015198505050505050505050919050565b60008184841115613064576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1919061394c565b505050900390565b60008061307842610ead565b9050600080613840600e548161308a57fe5b04905060005b818110156130e057808403600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a1684529091529020546130d69084906126af565b9250600101613090565b5090949350505050565b6000808211613125576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613fbb565b816001141561313657506000610ae6565b81600060805b60018110613184577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001821b01811b83161561317c5791821c91908101905b60011c61313c565b506001811b84146126ee576001019392505050565b60008181526005602052604090205460ff16156131e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190613e6d565b600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b600061322783836117aa565b60008181526004602052604090205490915015613270576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e190614018565b600082116132aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e1906141f8565b6040805160608101825283815260006020808301828152428486019081528684526004909252918490209251835590516001830155516002909101555183907fb33d2162aead99dab59e77a7a67ea025b776bf8ca8079e132afdf9b23e03bd4290613316908590613943565b60405180910390a2505050565b60405180606001604052806000815260200160008152602001600081525090565b6040518061020001604052806010906020820280368337509192915050565b60008083601f840112613374578182fd5b50813567ffffffffffffffff81111561338b578182fd5b60208301915083602080830285010111156133a557600080fd5b9250929050565b6000602082840312156133bd578081fd5b81356126ee81614771565b600080600080606085870312156133dd578283fd5b84356133e881614771565b9350602085013567ffffffffffffffff811115613403578384fd5b61340f87828801613363565b9598909750949560400135949350505050565b60008060408385031215613434578182fd5b823561343f81614771565b946020939093013593505050565b60008060008060008060008060e0898b031215613468578384fd5b883561347381614771565b97506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff8111156134aa578384fd5b6134b68b828c01613363565b999c989b50969995989497949560c00135949350505050565b600080600080608085870312156134e4578384fd5b84356134ef81614771565b966020860135965060408601359560600135945092505050565b6000806000806000806000806000806000806101608d8f03121561352b578384fd5b6135358d35614771565b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d0135935067ffffffffffffffff6101208e0135111561358b578283fd5b61359c8e6101208f01358f01613363565b81945080935050506101408d013590509295989b509295989b509295989b565b6000602082840312156135cd578081fd5b5035919050565b600080604083850312156135e6578182fd5b50508035926020909101359150565b600080600060608486031215613609578283fd5b8335925060208401359150604084013561362281614771565b809150509250925092565b600080600060608486031215613641578081fd5b505081359360208301359350604090920135919050565b6000806040838503121561366a578182fd5b82359150602083013561367c81614771565b809150509250929050565b600080600080600080600060e0888a0312156136a1578081fd5b8735965060208801356136b381614771565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600080600060e0888a0312156136f9578081fd5b87359650602088013561370b81614771565b955060408801359450606088013593506080880135925060a088013561373081614771565b8092505060c0880135905092959891949750929550565b60008060408385031215613759578182fd5b823591506020830135801515811461367c578182fd5b600080600080600060a08688031215613786578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b600081518084526137c1816020860160208601614745565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b918252602082015260400190565b60008251613813818460208701614745565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff851682526040602083015282604083015282846060840137818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015290151560a082015260c00190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b901515815260200190565b90815260200190565b6000602082526126ee60208301846137a9565b60208082526027908201527f4c315f4252473a204d757374207472616e736665722061206e6f6e2d7a65726f60408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f4c315f4554485f4252473a20455448207472616e73666572206661696c656400604082015260600190565b6020808252603b908201527f4c315f4252473a206368616c6c656e6765506572696f64206d7573742062652060408201527f646976697369626c652062792054494d455f534c4f545f53495a450000000000606082015260800190565b6020808252601f908201527f4c315f4252473a2043616c6c6572206973206e6f7420746865206f776e657200604082015260600190565b60208082526028908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e20626f6e646564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f4c325f4252473a207472616e73666572496420686173206e6f20626f6e640000604082015260600190565b6020808252601c908201527f4252473a205472616e7366657220726f6f74206e6f7420666f756e6400000000604082015260600190565b6020808252601e908201527f4143543a204164647265737320697320616c726561647920626f6e6465720000604082015260600190565b6020808252601b908201527f4252473a205472616e73666572526f6f74206e6f7420666f756e640000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526025908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792072657360408201527f6f6c766564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792063686160408201527f6c6c656e67656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4252473a205472616e73666572526f6f742063616e6e6f74206265207265736360408201527f756564206265666f726520746865205265736375652044656c61790000000000606082015260800190565b6020808252601a908201527f4143543a2041646472657373206973206e6f7420626f6e646572000000000000604082015260600190565b60208082526028908201527f4c315f4252473a2053656e647320746f207468697320636861696e496420617260408201527f6520706175736564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602e908201527f4c315f4252473a20726f6f74436f6d6d69747465644174206d7573742062652060408201527f67726561746572207468616e2030000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252602c908201527f4252473a20546865207472616e736665722068617320616c726561647920626560408201527f656e2077697468647261776e0000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4554485f4252473a2056616c756520646f6573206e6f74206d6174636860408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4c69625f4d65726b6c65547265653a20496e646578206f7574206f6620626f7560408201527f6e64732e00000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f4c315f4252473a20636861696e4964206e6f7420737570706f72746564000000604082015260600190565b60208082526030908201527f4c69625f4d65726b6c65547265653a2043616e6e6f7420636f6d70757465206360408201527f65696c286c6f675f3229206f6620302e00000000000000000000000000000000606082015260800190565b6020808252601e908201527f4252473a205472616e7366657220726f6f7420616c7265616479207365740000604082015260600190565b60208082526026908201527f4c315f4252473a205472616e73666572526f6f7420616c726561647920636f6e60408201527f6669726d65640000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20636f6e6669726d65640000000000000000000000000000000000606082015260800190565b60208082526037908201527f4c69625f4d65726b6c65547265653a20546f74616c206c6561766573206d757360408201527f742062652067726561746572207468616e207a65726f2e000000000000000000606082015260800190565b6020808252818101527f4143543a204e6f7420656e6f75676820617661696c61626c6520637265646974604082015260600190565b6020808252602d908201527f4252473a2043616e6e6f7420736574205472616e73666572526f6f7420746f7460408201527f616c416d6f756e74206f66203000000000000000000000000000000000000000606082015260800190565b60208082526019908201527f4143543a2043616c6c6572206973206e6f7420626f6e64657200000000000000604082015260600190565b6020808252601b908201527f4252473a20496e76616c6964207472616e736665722070726f6f660000000000604082015260600190565b602080825260409082018190527f4c315f4252473a205472616e73666572526f6f742063616e6e6f742062652063908201527f68616c6c656e676564206166746572206368616c6c656e676520706572696f64606082015260800190565b60208082526026908201527f4c315f4252473a204368616c6c656e676520706572696f6420686173206e6f7460408201527f20656e6465640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252604d908201527f4c69625f4d65726b6c65547265653a20546f74616c207369626c696e6773206460408201527f6f6573206e6f7420636f72726563746c7920636f72726573706f6e6420746f2060608201527f746f74616c206c65617665732e00000000000000000000000000000000000000608082015260a00190565b60208082526027908201527f4252473a205769746864726177616c2068617320616c7265616479206265656e60408201527f20626f6e64656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e206368616c6c656e6765640000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4252473a205769746864726177616c2065786365656473205472616e7366657260408201527f526f6f7420746f74616c00000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4c315f4252473a205f6e6577476f7665726e616e63652063616e6e6f7420626560408201527f2061646472657373283029000000000000000000000000000000000000000000606082015260800190565b60208082526034908201527f4c69625f4d65726b6c65547265653a204d7573742070726f766964652061742060408201527f6c65617374206f6e65206c65616620686173682e000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20626f6e6465640000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f4c315f4252473a2052656c61796572206665652063616e6e6f7420657863656560408201527f6420616d6f756e74000000000000000000000000000000000000000000000000606082015260800190565b81518152602080830151908201526040918201519181019190915260600190565b96875273ffffffffffffffffffffffffffffffffffffffff95909516602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b93845260208401929092526040830152606082015260800190565b60005b83811015614760578181015183820152602001614748565b83811115610ea75750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114610fa857600080fdfe4c315f4252473a20416d6f756e74206578636565647320636861696e42616c616e63652e205468697320696e646963617465732061206c617965722d32206661696c7572652ea2646970667358221220059efbacfa8e4391e713a70ec9b5c2c2563c7f47558e9ce3c7e1c29a5888cbe664736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb00000000000000000000000000000000000000000000000000000000000000020000000000000000000000002a6303e6b99d451df3566068ebb110708335658f0000000000000000000000009137a628546e2b1bc26f60a5d1262fb6d58ea44a
-----Decoded View---------------
Arg [0] : bonders (address[]): 0x2A6303e6b99d451Df3566068EBb110708335658f,0x9137a628546e2b1bc26F60A5D1262fb6D58eA44A
Arg [1] : _governance (address): 0xF56e305024B195383245A075737d16dBdb8487Fb
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [3] : 0000000000000000000000002a6303e6b99d451df3566068ebb110708335658f
Arg [4] : 0000000000000000000000009137a628546e2b1bc26f60a5d1262fb6d58ea44a
Loading...
Loading
Loading...
Loading
Net Worth in USD
$1,215,826.12
Net Worth in ETH
613.080904
Token Allocations
ETH
99.96%
LINK
0.02%
PYUSD
0.01%
Others
0.01%
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 99.96% | $1,982.51 | 613.0445 | $1,215,368.12 | |
| ETH | 0.02% | $8.73 | 30.722 | $268.2 | |
| ETH | <0.01% | $0.999711 | 91.4165 | $91.39 | |
| ETH | <0.01% | $0.999954 | 44.8817 | $44.88 | |
| ETH | <0.01% | $1,982.51 | 0.00180528 | $3.58 | |
| ETH | <0.01% | $0.000014 | 111,858.1012 | $1.53 | |
| ETH | <0.01% | $0.000206 | 1,082 | $0.2224 | |
| ETH | <0.01% | <$0.000001 | 41,292,938.5214 | $0.1634 | |
| BSC | <0.01% | $613.37 | 0.0665 | $40.8 | |
| OP | <0.01% | $0.99968 | 5.984 | $5.98 | |
| OP | <0.01% | $0.999575 | 0.11 | $0.1099 | |
| BASE | <0.01% | $1,982.53 | 0.00057197 | $1.13 | |
| GNO | <0.01% | $0.999943 | 0.002 | $0.002 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.