ETH Price: $3,361.27 (+0.29%)

Contract

0xa4108aA1Ec4967F8b52220a4f7e94A8201F2D906
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Send To Cosmos212497592024-11-23 10:11:232 hrs ago1732356683IN
Gravity Bridge: Bridge
0 ETH0.0006137111.00871785
Send To Cosmos212488222024-11-23 7:03:355 hrs ago1732345415IN
Gravity Bridge: Bridge
0 ETH0.00059479.48057437
Send To Cosmos212478572024-11-23 3:49:598 hrs ago1732333799IN
Gravity Bridge: Bridge
0 ETH0.0007185110.63816205
Submit Batch212477662024-11-23 3:31:478 hrs ago1732332707IN
Gravity Bridge: Bridge
0 ETH0.0029207510.28647536
Send To Cosmos212472962024-11-23 1:57:3510 hrs ago1732327055IN
Gravity Bridge: Bridge
0 ETH0.0008471411.8807231
Send To Cosmos212470152024-11-23 1:00:5911 hrs ago1732323659IN
Gravity Bridge: Bridge
0 ETH0.000721913.04723423
Send To Cosmos212467662024-11-23 0:11:1112 hrs ago1732320671IN
Gravity Bridge: Bridge
0 ETH0.0007967314.40273
Send To Cosmos212464752024-11-22 23:12:3513 hrs ago1732317155IN
Gravity Bridge: Bridge
0 ETH0.0008158413.47434223
Send To Cosmos212464222024-11-22 23:01:5913 hrs ago1732316519IN
Gravity Bridge: Bridge
0 ETH0.0008712615.62525079
Send To Cosmos212458492024-11-22 21:06:5915 hrs ago1732309619IN
Gravity Bridge: Bridge
0 ETH0.0011086618.97267614
Send To Cosmos212452402024-11-22 19:04:5917 hrs ago1732302299IN
Gravity Bridge: Bridge
0 ETH0.0010610714.88097164
Submit Batch212448842024-11-22 17:53:4718 hrs ago1732298027IN
Gravity Bridge: Bridge
0 ETH0.0052233215.10823494
Send To Cosmos212447622024-11-22 17:28:3518 hrs ago1732296515IN
Gravity Bridge: Bridge
0 ETH0.0008154115.09883429
Send To Cosmos212446782024-11-22 17:11:3519 hrs ago1732295495IN
Gravity Bridge: Bridge
0 ETH0.0009035114.34817562
Send To Cosmos212441232024-11-22 15:19:2320 hrs ago1732288763IN
Gravity Bridge: Bridge
0 ETH0.0011043615.4933294
Send To Cosmos212439712024-11-22 14:48:5921 hrs ago1732286939IN
Gravity Bridge: Bridge
0 ETH0.0010308814.46002952
Send To Cosmos212439462024-11-22 14:43:5921 hrs ago1732286639IN
Gravity Bridge: Bridge
0 ETH0.0010532215.84271709
Send To Cosmos212434512024-11-22 13:04:2323 hrs ago1732280663IN
Gravity Bridge: Bridge
0 ETH0.0010298114.44746755
Send To Cosmos212429152024-11-22 11:16:3524 hrs ago1732274195IN
Gravity Bridge: Bridge
0 ETH0.0006148210.15436382
Send To Cosmos212427382024-11-22 10:41:1125 hrs ago1732272071IN
Gravity Bridge: Bridge
0 ETH0.0007863712.98764926
Submit Batch212417512024-11-22 7:22:4728 hrs ago1732260167IN
Gravity Bridge: Bridge
0 ETH0.001198267.56038662
Submit Batch212416382024-11-22 7:00:1129 hrs ago1732258811IN
Gravity Bridge: Bridge
0 ETH0.002404087.67610879
Submit Batch212413112024-11-22 5:53:5930 hrs ago1732254839IN
Gravity Bridge: Bridge
0 ETH0.003262119.00932942
Submit Batch212408522024-11-22 4:21:4731 hrs ago1732249307IN
Gravity Bridge: Bridge
0 ETH0.0193537757.56969211
Send To Cosmos212408462024-11-22 4:20:3531 hrs ago1732249235IN
Gravity Bridge: Bridge
0 ETH0.000678439.51462702
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
197909722024-05-03 17:07:11203 days ago1714756031
Gravity Bridge: Bridge
 Contract Creation0 ETH
189972332024-01-13 9:59:59315 days ago1705139999
Gravity Bridge: Bridge
 Contract Creation0 ETH
189772232024-01-10 14:44:11317 days ago1704897851
Gravity Bridge: Bridge
 Contract Creation0 ETH
186808462023-11-30 0:28:23359 days ago1701304103
Gravity Bridge: Bridge
 Contract Creation0 ETH
174445052023-06-09 18:40:47532 days ago1686336047
Gravity Bridge: Bridge
 Contract Creation0 ETH
167334522023-03-01 11:23:59633 days ago1677669839
Gravity Bridge: Bridge
 Contract Creation0 ETH
167334142023-03-01 11:16:11633 days ago1677669371
Gravity Bridge: Bridge
 Contract Creation0 ETH
166909472023-02-23 11:58:11639 days ago1677153491
Gravity Bridge: Bridge
 Contract Creation0 ETH
165418212023-02-02 14:50:35659 days ago1675349435
Gravity Bridge: Bridge
 Contract Creation0 ETH
164898912023-01-26 8:47:59667 days ago1674722879
Gravity Bridge: Bridge
 Contract Creation0 ETH
164898672023-01-26 8:43:11667 days ago1674722591
Gravity Bridge: Bridge
 Contract Creation0 ETH
164898642023-01-26 8:42:35667 days ago1674722555
Gravity Bridge: Bridge
 Contract Creation0 ETH
161674302022-12-12 8:26:47712 days ago1670833607
Gravity Bridge: Bridge
 Contract Creation0 ETH
158753962022-11-01 13:12:35752 days ago1667308355
Gravity Bridge: Bridge
 Contract Creation0 ETH
158753922022-11-01 13:11:47752 days ago1667308307
Gravity Bridge: Bridge
 Contract Creation0 ETH
158408122022-10-27 17:10:23757 days ago1666890623
Gravity Bridge: Bridge
 Contract Creation0 ETH
158159552022-10-24 5:43:59761 days ago1666590239
Gravity Bridge: Bridge
 Contract Creation0 ETH
158159272022-10-24 5:38:11761 days ago1666589891
Gravity Bridge: Bridge
 Contract Creation0 ETH
151743562022-07-19 17:16:32857 days ago1658250992
Gravity Bridge: Bridge
 Contract Creation0 ETH
143929762022-03-15 19:12:17983 days ago1647371537
Gravity Bridge: Bridge
 Contract Creation0 ETH
142762162022-02-25 15:56:551001 days ago1645804615
Gravity Bridge: Bridge
 Contract Creation0 ETH
142761912022-02-25 15:51:051001 days ago1645804265
Gravity Bridge: Bridge
 Contract Creation0 ETH
142761572022-02-25 15:43:211001 days ago1645803801
Gravity Bridge: Bridge
 Contract Creation0 ETH
142737252022-02-25 6:39:561002 days ago1645771196
Gravity Bridge: Bridge
 Contract Creation0 ETH
141291152022-02-02 21:44:411024 days ago1643838281
Gravity Bridge: Bridge
 Contract Creation0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Gravity

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 10 : Gravity.sol
//SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./CosmosToken.sol";

error InvalidSignature();
error InvalidValsetNonce(uint256 newNonce, uint256 currentNonce);
error InvalidBatchNonce(uint256 newNonce, uint256 currentNonce);
error InvalidLogicCallNonce(uint256 newNonce, uint256 currentNonce);
error InvalidLogicCallTransfers();
error InvalidLogicCallFees();
error InvalidSendToCosmos();
error IncorrectCheckpoint();
error MalformedNewValidatorSet();
error MalformedCurrentValidatorSet();
error MalformedBatch();
error InsufficientPower(uint256 cumulativePower, uint256 powerThreshold);
error BatchTimedOut();
error LogicCallTimedOut();

// This is being used purely to avoid stack too deep errors
struct LogicCallArgs {
	// Transfers out to the logic contract
	uint256[] transferAmounts;
	address[] transferTokenContracts;
	// The fees (transferred to msg.sender)
	uint256[] feeAmounts;
	address[] feeTokenContracts;
	// The arbitrary logic call
	address logicContractAddress;
	bytes payload;
	// Invalidation metadata
	uint256 timeOut;
	bytes32 invalidationId;
	uint256 invalidationNonce;
}

// This is used purely to avoid stack too deep errors
// represents everything about a given validator set
struct ValsetArgs {
	// the validators in this set, represented by an Ethereum address
	address[] validators;
	// the powers of the given validators in the same order as above
	uint256[] powers;
	// the nonce of this validator set
	uint256 valsetNonce;
	// the reward amount denominated in the below reward token, can be
	// set to zero
	uint256 rewardAmount;
	// the reward token, should be set to the zero address if not being used
	address rewardToken;
}

// This represents a validator signature
struct Signature {
	uint8 v;
	bytes32 r;
	bytes32 s;
}

contract Gravity is ReentrancyGuard {
	using SafeERC20 for IERC20;

	// The number of 'votes' required to execute a valset
	// update or batch execution, set to 2/3 of 2^32
	uint256 constant constant_powerThreshold = 2863311530;

	// These are updated often
	bytes32 public state_lastValsetCheckpoint;
	mapping(address => uint256) public state_lastBatchNonces;
	mapping(bytes32 => uint256) public state_invalidationMapping;
	uint256 public state_lastValsetNonce = 0;
	// event nonce zero is reserved by the Cosmos module as a special
	// value indicating that no events have yet been submitted
	uint256 public state_lastEventNonce = 1;

	// This is set once at initialization
	bytes32 public immutable state_gravityId;

	// TransactionBatchExecutedEvent and SendToCosmosEvent both include the field _eventNonce.
	// This is incremented every time one of these events is emitted. It is checked by the
	// Cosmos module to ensure that all events are received in order, and that none are lost.
	//
	// ValsetUpdatedEvent does not include the field _eventNonce because it is never submitted to the Cosmos
	// module. It is purely for the use of relayers to allow them to successfully submit batches.
	event TransactionBatchExecutedEvent(
		uint256 indexed _batchNonce,
		address indexed _token,
		uint256 _eventNonce
	);
	event SendToCosmosEvent(
		address indexed _tokenContract,
		address indexed _sender,
		string _destination,
		uint256 _amount,
		uint256 _eventNonce
	);
	event ERC20DeployedEvent(
		// FYI: Can't index on a string without doing a bunch of weird stuff
		string _cosmosDenom,
		address indexed _tokenContract,
		string _name,
		string _symbol,
		uint8 _decimals,
		uint256 _eventNonce
	);
	event ValsetUpdatedEvent(
		uint256 indexed _newValsetNonce,
		uint256 _eventNonce,
		uint256 _rewardAmount,
		address _rewardToken,
		address[] _validators,
		uint256[] _powers
	);
	event LogicCallEvent(
		bytes32 _invalidationId,
		uint256 _invalidationNonce,
		bytes _returnData,
		uint256 _eventNonce
	);

	// TEST FIXTURES
	// These are here to make it easier to measure gas usage. They should be removed before production
	function testMakeCheckpoint(ValsetArgs calldata _valsetArgs, bytes32 _gravityId) external pure {
		makeCheckpoint(_valsetArgs, _gravityId);
	}

	function testCheckValidatorSignatures(
		ValsetArgs calldata _currentValset,
		Signature[] calldata _sigs,
		bytes32 _theHash,
		uint256 _powerThreshold
	) external pure {
		checkValidatorSignatures(_currentValset, _sigs, _theHash, _powerThreshold);
	}

	// END TEST FIXTURES

	function lastBatchNonce(address _erc20Address) external view returns (uint256) {
		return state_lastBatchNonces[_erc20Address];
	}

	function lastLogicCallNonce(bytes32 _invalidation_id) external view returns (uint256) {
		return state_invalidationMapping[_invalidation_id];
	}

	// Utility function to verify geth style signatures
	function verifySig(
		address _signer,
		bytes32 _theHash,
		Signature calldata _sig
	) private pure returns (bool) {
		bytes32 messageDigest = keccak256(
			abi.encodePacked("\x19Ethereum Signed Message:\n32", _theHash)
		);
		return _signer == ECDSA.recover(messageDigest, _sig.v, _sig.r, _sig.s);
	}

	// Utility function to determine that a validator set and signatures are well formed
	function validateValset(ValsetArgs calldata _valset, Signature[] calldata _sigs) private pure {
		// Check that current validators, powers, and signatures (v,r,s) set is well-formed
		if (
			_valset.validators.length != _valset.powers.length ||
			_valset.validators.length != _sigs.length
		) {
			revert MalformedCurrentValidatorSet();
		}
	}

	// Make a new checkpoint from the supplied validator set
	// A checkpoint is a hash of all relevant information about the valset. This is stored by the contract,
	// instead of storing the information directly. This saves on storage and gas.
	// The format of the checkpoint is:
	// h(gravityId, "checkpoint", valsetNonce, validators[], powers[])
	// Where h is the keccak256 hash function.
	// The validator powers must be decreasing or equal. This is important for checking the signatures on the
	// next valset, since it allows the caller to stop verifying signatures once a quorum of signatures have been verified.
	function makeCheckpoint(ValsetArgs memory _valsetArgs, bytes32 _gravityId)
		private
		pure
		returns (bytes32)
	{
		// bytes32 encoding of the string "checkpoint"
		bytes32 methodName = 0x636865636b706f696e7400000000000000000000000000000000000000000000;

		bytes32 checkpoint = keccak256(
			abi.encode(
				_gravityId,
				methodName,
				_valsetArgs.valsetNonce,
				_valsetArgs.validators,
				_valsetArgs.powers,
				_valsetArgs.rewardAmount,
				_valsetArgs.rewardToken
			)
		);

		return checkpoint;
	}

	function checkValidatorSignatures(
		// The current validator set and their powers
		ValsetArgs calldata _currentValset,
		// The current validator's signatures
		Signature[] calldata _sigs,
		// This is what we are checking they have signed
		bytes32 _theHash,
		uint256 _powerThreshold
	) private pure {
		uint256 cumulativePower = 0;

		for (uint256 i = 0; i < _currentValset.validators.length; i++) {
			// If v is set to 0, this signifies that it was not possible to get a signature from this validator and we skip evaluation
			// (In a valid signature, it is either 27 or 28)
			if (_sigs[i].v != 0) {
				// Check that the current validator has signed off on the hash
				if (!verifySig(_currentValset.validators[i], _theHash, _sigs[i])) {
					revert InvalidSignature();
				}

				// Sum up cumulative power
				cumulativePower = cumulativePower + _currentValset.powers[i];

				// Break early to avoid wasting gas
				if (cumulativePower > _powerThreshold) {
					break;
				}
			}
		}

		// Check that there was enough power
		if (cumulativePower <= _powerThreshold) {
			revert InsufficientPower(cumulativePower, _powerThreshold);
		}
		// Success
	}

	// This updates the valset by checking that the validators in the current valset have signed off on the
	// new valset. The signatures supplied are the signatures of the current valset over the checkpoint hash
	// generated from the new valset.
	// Anyone can call this function, but they must supply valid signatures of constant_powerThreshold of the current valset over
	// the new valset.
	function updateValset(
		// The new version of the validator set
		ValsetArgs calldata _newValset,
		// The current validators that approve the change
		ValsetArgs calldata _currentValset,
		// These are arrays of the parts of the current validator's signatures
		Signature[] calldata _sigs
	) external {
		// CHECKS

		// Check that the valset nonce is greater than the old one
		if (_newValset.valsetNonce <= _currentValset.valsetNonce) {
			revert InvalidValsetNonce({
				newNonce: _newValset.valsetNonce,
				currentNonce: _currentValset.valsetNonce
			});
		}

		// Check that the valset nonce is less than a million nonces forward from the old one
		// this makes it difficult for an attacker to lock out the contract by getting a single
		// bad validator set through with uint256 max nonce
		if (_newValset.valsetNonce > _currentValset.valsetNonce + 1000000) {
			revert InvalidValsetNonce({
				newNonce: _newValset.valsetNonce,
				currentNonce: _currentValset.valsetNonce
			});
		}

		// Check that new validators and powers set is well-formed
		if (
			_newValset.validators.length != _newValset.powers.length ||
			_newValset.validators.length == 0
		) {
			revert MalformedNewValidatorSet();
		}

		// Check that current validators, powers, and signatures (v,r,s) set is well-formed
		validateValset(_currentValset, _sigs);

		// Check cumulative power to ensure the contract has sufficient power to actually
		// pass a vote
		uint256 cumulativePower = 0;
		for (uint256 i = 0; i < _newValset.powers.length; i++) {
			cumulativePower = cumulativePower + _newValset.powers[i];
			if (cumulativePower > constant_powerThreshold) {
				break;
			}
		}
		if (cumulativePower <= constant_powerThreshold) {
			revert InsufficientPower({
				cumulativePower: cumulativePower,
				powerThreshold: constant_powerThreshold
			});
		}

		// Check that the supplied current validator set matches the saved checkpoint
		if (makeCheckpoint(_currentValset, state_gravityId) != state_lastValsetCheckpoint) {
			revert IncorrectCheckpoint();
		}

		// Check that enough current validators have signed off on the new validator set
		bytes32 newCheckpoint = makeCheckpoint(_newValset, state_gravityId);

		checkValidatorSignatures(_currentValset, _sigs, newCheckpoint, constant_powerThreshold);

		// ACTIONS

		// Stored to be used next time to validate that the valset
		// supplied by the caller is correct.
		state_lastValsetCheckpoint = newCheckpoint;

		// Store new nonce
		state_lastValsetNonce = _newValset.valsetNonce;

		// Send submission reward to msg.sender if reward token is a valid value
		if (_newValset.rewardToken != address(0) && _newValset.rewardAmount != 0) {
			IERC20(_newValset.rewardToken).safeTransfer(msg.sender, _newValset.rewardAmount);
		}

		// LOGS

		state_lastEventNonce = state_lastEventNonce + 1;
		emit ValsetUpdatedEvent(
			_newValset.valsetNonce,
			state_lastEventNonce,
			_newValset.rewardAmount,
			_newValset.rewardToken,
			_newValset.validators,
			_newValset.powers
		);
	}

	// submitBatch processes a batch of Cosmos -> Ethereum transactions by sending the tokens in the transactions
	// to the destination addresses. It is approved by the current Cosmos validator set.
	// Anyone can call this function, but they must supply valid signatures of constant_powerThreshold of the current valset over
	// the batch.
	function submitBatch(
		// The validators that approve the batch
		ValsetArgs calldata _currentValset,
		// These are arrays of the parts of the validators signatures
		Signature[] calldata _sigs,
		// The batch of transactions
		uint256[] calldata _amounts,
		address[] calldata _destinations,
		uint256[] calldata _fees,
		uint256 _batchNonce,
		address _tokenContract,
		// a block height beyond which this batch is not valid
		// used to provide a fee-free timeout
		uint256 _batchTimeout
	) external nonReentrant {
		// CHECKS scoped to reduce stack depth
		{
			// Check that the batch nonce is higher than the last nonce for this token
			if (_batchNonce <= state_lastBatchNonces[_tokenContract]) {
				revert InvalidBatchNonce({
					newNonce: _batchNonce,
					currentNonce: state_lastBatchNonces[_tokenContract]
				});
			}

			// Check that the batch nonce is less than one million nonces forward from the old one
			// this makes it difficult for an attacker to lock out the contract by getting a single
			// bad batch through with uint256 max nonce
			if (_batchNonce > state_lastBatchNonces[_tokenContract] + 1000000) {
				revert InvalidBatchNonce({
					newNonce: _batchNonce,
					currentNonce: state_lastBatchNonces[_tokenContract]
				});
			}

			// Check that the block height is less than the timeout height
			if (block.number >= _batchTimeout) {
				revert BatchTimedOut();
			}

			// Check that current validators, powers, and signatures (v,r,s) set is well-formed
			validateValset(_currentValset, _sigs);

			// Check that the supplied current validator set matches the saved checkpoint
			if (makeCheckpoint(_currentValset, state_gravityId) != state_lastValsetCheckpoint) {
				revert IncorrectCheckpoint();
			}

			// Check that the transaction batch is well-formed
			if (_amounts.length != _destinations.length || _amounts.length != _fees.length) {
				revert MalformedBatch();
			}

			// Check that enough current validators have signed off on the transaction batch and valset
			checkValidatorSignatures(
				_currentValset,
				_sigs,
				// Get hash of the transaction batch and checkpoint
				keccak256(
					abi.encode(
						state_gravityId,
						// bytes32 encoding of "transactionBatch"
						0x7472616e73616374696f6e426174636800000000000000000000000000000000,
						_amounts,
						_destinations,
						_fees,
						_batchNonce,
						_tokenContract,
						_batchTimeout
					)
				),
				constant_powerThreshold
			);

			// ACTIONS

			// Store batch nonce
			state_lastBatchNonces[_tokenContract] = _batchNonce;

			{
				// Send transaction amounts to destinations
				uint256 totalFee;
				for (uint256 i = 0; i < _amounts.length; i++) {
					IERC20(_tokenContract).safeTransfer(_destinations[i], _amounts[i]);
					totalFee = totalFee + _fees[i];
				}

				// Send transaction fees to msg.sender
				IERC20(_tokenContract).safeTransfer(msg.sender, totalFee);
			}
		}

		// LOGS scoped to reduce stack depth
		{
			state_lastEventNonce = state_lastEventNonce + 1;
			emit TransactionBatchExecutedEvent(_batchNonce, _tokenContract, state_lastEventNonce);
		}
	}

	// This makes calls to contracts that execute arbitrary logic
	// First, it gives the logic contract some tokens
	// Then, it gives msg.senders tokens for fees
	// Then, it calls an arbitrary function on the logic contract
	// invalidationId and invalidationNonce are used for replay prevention.
	// They can be used to implement a per-token nonce by setting the token
	// address as the invalidationId and incrementing the nonce each call.
	// They can be used for nonce-free replay prevention by using a different invalidationId
	// for each call.
	function submitLogicCall(
		// The validators that approve the call
		ValsetArgs calldata _currentValset,
		// These are arrays of the parts of the validators signatures
		Signature[] calldata _sigs,
		LogicCallArgs memory _args
	) external nonReentrant {
		// CHECKS scoped to reduce stack depth
		{
			// Check that the call has not timed out
			if (block.number >= _args.timeOut) {
				revert LogicCallTimedOut();
			}

			// Check that the invalidation nonce is higher than the last nonce for this invalidation Id
			if (state_invalidationMapping[_args.invalidationId] >= _args.invalidationNonce) {
				revert InvalidLogicCallNonce({
					newNonce: _args.invalidationNonce,
					currentNonce: state_invalidationMapping[_args.invalidationId]
				});
			}

			// note the lack of nonce skipping check, it's not needed here since an attacker
			// will never be able to fill the invalidationId space, therefore a nonce lockout
			// is simply not possible

			// Check that current validators, powers, and signatures (v,r,s) set is well-formed
			validateValset(_currentValset, _sigs);

			// Check that the supplied current validator set matches the saved checkpoint
			if (makeCheckpoint(_currentValset, state_gravityId) != state_lastValsetCheckpoint) {
				revert IncorrectCheckpoint();
			}

			if (_args.transferAmounts.length != _args.transferTokenContracts.length) {
				revert InvalidLogicCallTransfers();
			}

			if (_args.feeAmounts.length != _args.feeTokenContracts.length) {
				revert InvalidLogicCallFees();
			}
		}
		{
			bytes32 argsHash = keccak256(
				abi.encode(
					state_gravityId,
					// bytes32 encoding of "logicCall"
					0x6c6f67696343616c6c0000000000000000000000000000000000000000000000,
					_args.transferAmounts,
					_args.transferTokenContracts,
					_args.feeAmounts,
					_args.feeTokenContracts,
					_args.logicContractAddress,
					_args.payload,
					_args.timeOut,
					_args.invalidationId,
					_args.invalidationNonce
				)
			);

			// Check that enough current validators have signed off on the transaction batch and valset
			checkValidatorSignatures(
				_currentValset,
				_sigs,
				// Get hash of the transaction batch and checkpoint
				argsHash,
				constant_powerThreshold
			);
		}

		// ACTIONS

		// Update invaldiation nonce
		state_invalidationMapping[_args.invalidationId] = _args.invalidationNonce;

		// Send tokens to the logic contract
		for (uint256 i = 0; i < _args.transferAmounts.length; i++) {
			IERC20(_args.transferTokenContracts[i]).safeTransfer(
				_args.logicContractAddress,
				_args.transferAmounts[i]
			);
		}

		// Make call to logic contract
		bytes memory returnData = Address.functionCall(_args.logicContractAddress, _args.payload);

		// Send fees to msg.sender
		for (uint256 i = 0; i < _args.feeAmounts.length; i++) {
			IERC20(_args.feeTokenContracts[i]).safeTransfer(msg.sender, _args.feeAmounts[i]);
		}

		// LOGS scoped to reduce stack depth
		{
			state_lastEventNonce = state_lastEventNonce + 1;
			emit LogicCallEvent(
				_args.invalidationId,
				_args.invalidationNonce,
				returnData,
				state_lastEventNonce
			);
		}
	}

	function sendToCosmos(
		address _tokenContract,
		string calldata _destination,
		uint256 _amount
	) external nonReentrant {
		// we snapshot our current balance of this token
		uint256 ourStartingBalance = IERC20(_tokenContract).balanceOf(address(this));

		// attempt to transfer the user specified amount
		IERC20(_tokenContract).safeTransferFrom(msg.sender, address(this), _amount);

		// check what this particular ERC20 implementation actually gave us, since it doesn't
		// have to be at all related to the _amount
		uint256 ourEndingBalance = IERC20(_tokenContract).balanceOf(address(this));

		// a very strange ERC20 may trigger this condition, if we didn't have this we would
		// underflow, so it's mostly just an error message printer
		if (ourEndingBalance <= ourStartingBalance) {
			revert InvalidSendToCosmos();
		}

		state_lastEventNonce = state_lastEventNonce + 1;

		// emit to Cosmos the actual amount our balance has changed, rather than the user
		// provided amount. This protects against a small set of wonky ERC20 behavior, like
		// burning on send but not tokens that for example change every users balance every day.
		emit SendToCosmosEvent(
			_tokenContract,
			msg.sender,
			_destination,
			ourEndingBalance - ourStartingBalance,
			state_lastEventNonce
		);
	}

	function deployERC20(
		string calldata _cosmosDenom,
		string calldata _name,
		string calldata _symbol,
		uint8 _decimals
	) external {
		// Deploy an ERC20 with entire supply granted to Gravity.sol
		CosmosERC20 erc20 = new CosmosERC20(address(this), _name, _symbol, _decimals);

		// Fire an event to let the Cosmos module know
		state_lastEventNonce = state_lastEventNonce + 1;
		emit ERC20DeployedEvent(
			_cosmosDenom,
			address(erc20),
			_name,
			_symbol,
			_decimals,
			state_lastEventNonce
		);
	}

	constructor(
		// A unique identifier for this gravity instance to use in signatures
		bytes32 _gravityId,
		// The validator set, not in valset args format since many of it's
		// arguments would never be used in this case
		address[] memory _validators,
		uint256[] memory _powers
	) {
		// CHECKS

		// Check that validators, powers, and signatures (v,r,s) set is well-formed
		if (_validators.length != _powers.length || _validators.length == 0) {
			revert MalformedCurrentValidatorSet();
		}

		// Check cumulative power to ensure the contract has sufficient power to actually
		// pass a vote
		uint256 cumulativePower = 0;
		for (uint256 i = 0; i < _powers.length; i++) {
			cumulativePower = cumulativePower + _powers[i];
			if (cumulativePower > constant_powerThreshold) {
				break;
			}
		}
		if (cumulativePower <= constant_powerThreshold) {
			revert InsufficientPower({
				cumulativePower: cumulativePower,
				powerThreshold: constant_powerThreshold
			});
		}

		ValsetArgs memory _valset;
		_valset = ValsetArgs(_validators, _powers, 0, 0, address(0));

		bytes32 newCheckpoint = makeCheckpoint(_valset, _gravityId);

		// ACTIONS

		state_gravityId = _gravityId;
		state_lastValsetCheckpoint = newCheckpoint;

		// LOGS

		emit ValsetUpdatedEvent(
			state_lastValsetNonce,
			state_lastEventNonce,
			0,
			address(0),
			_validators,
			_powers
		);
	}
}

File 2 of 10 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 3 of 10 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 4 of 10 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^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() {
        _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;
    }
}

File 5 of 10 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 6 of 10 : ECDSA.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s;
        uint8 v;
        assembly {
            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
            v := add(shr(255, vs), 27)
        }
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 7 of 10 : CosmosToken.sol
//SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract CosmosERC20 is ERC20 {
	uint256 MAX_UINT = 2**256 - 1;
	uint8 private cosmosDecimals;
	address private gravityAddress;

	// This override ensures we return the proper number of decimals
	// for the cosmos token
	function decimals() public view virtual override returns (uint8) {
		return cosmosDecimals;
	}

	// This is not an accurate total supply. Instead this is the total supply
	// of the given cosmos asset on Ethereum at this moment in time. Keeping
	// a totally accurate supply would require constant updates from the Cosmos
	// side, while in theory this could be piggy-backed on some existing bridge
	// operation it's a lot of complextiy to add so we chose to forgoe it.
	function totalSupply() public view virtual override returns (uint256) {
		return MAX_UINT - balanceOf(gravityAddress);
	}

	constructor(
		address _gravityAddress,
		string memory _name,
		string memory _symbol,
		uint8 _decimals
	) ERC20(_name, _symbol) {
		cosmosDecimals = _decimals;
		gravityAddress = _gravityAddress;
		_mint(_gravityAddress, MAX_UINT);
	}
}

File 8 of 10 : ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 9 of 10 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 10 of 10 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"bytes32","name":"_gravityId","type":"bytes32"},{"internalType":"address[]","name":"_validators","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BatchTimedOut","type":"error"},{"inputs":[],"name":"IncorrectCheckpoint","type":"error"},{"inputs":[{"internalType":"uint256","name":"cumulativePower","type":"uint256"},{"internalType":"uint256","name":"powerThreshold","type":"uint256"}],"name":"InsufficientPower","type":"error"},{"inputs":[{"internalType":"uint256","name":"newNonce","type":"uint256"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidBatchNonce","type":"error"},{"inputs":[],"name":"InvalidLogicCallFees","type":"error"},{"inputs":[{"internalType":"uint256","name":"newNonce","type":"uint256"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidLogicCallNonce","type":"error"},{"inputs":[],"name":"InvalidLogicCallTransfers","type":"error"},{"inputs":[],"name":"InvalidSendToCosmos","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"newNonce","type":"uint256"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidValsetNonce","type":"error"},{"inputs":[],"name":"LogicCallTimedOut","type":"error"},{"inputs":[],"name":"MalformedBatch","type":"error"},{"inputs":[],"name":"MalformedCurrentValidatorSet","type":"error"},{"inputs":[],"name":"MalformedNewValidatorSet","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"_cosmosDenom","type":"string"},{"indexed":true,"internalType":"address","name":"_tokenContract","type":"address"},{"indexed":false,"internalType":"string","name":"_name","type":"string"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint8","name":"_decimals","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"ERC20DeployedEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_invalidationId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_invalidationNonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"_returnData","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"LogicCallEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tokenContract","type":"address"},{"indexed":true,"internalType":"address","name":"_sender","type":"address"},{"indexed":false,"internalType":"string","name":"_destination","type":"string"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"SendToCosmosEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_batchNonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"}],"name":"TransactionBatchExecutedEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_newValsetNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_eventNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_rewardAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_rewardToken","type":"address"},{"indexed":false,"internalType":"address[]","name":"_validators","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"ValsetUpdatedEvent","type":"event"},{"inputs":[{"internalType":"string","name":"_cosmosDenom","type":"string"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"}],"name":"deployERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_erc20Address","type":"address"}],"name":"lastBatchNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_invalidation_id","type":"bytes32"}],"name":"lastLogicCallNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenContract","type":"address"},{"internalType":"string","name":"_destination","type":"string"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"sendToCosmos","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"state_gravityId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"state_invalidationMapping","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"state_lastBatchNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastEventNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastValsetCheckpoint","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state_lastValsetNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_currentValset","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature[]","name":"_sigs","type":"tuple[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"address[]","name":"_destinations","type":"address[]"},{"internalType":"uint256[]","name":"_fees","type":"uint256[]"},{"internalType":"uint256","name":"_batchNonce","type":"uint256"},{"internalType":"address","name":"_tokenContract","type":"address"},{"internalType":"uint256","name":"_batchTimeout","type":"uint256"}],"name":"submitBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_currentValset","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature[]","name":"_sigs","type":"tuple[]"},{"components":[{"internalType":"uint256[]","name":"transferAmounts","type":"uint256[]"},{"internalType":"address[]","name":"transferTokenContracts","type":"address[]"},{"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"},{"internalType":"address[]","name":"feeTokenContracts","type":"address[]"},{"internalType":"address","name":"logicContractAddress","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint256","name":"timeOut","type":"uint256"},{"internalType":"bytes32","name":"invalidationId","type":"bytes32"},{"internalType":"uint256","name":"invalidationNonce","type":"uint256"}],"internalType":"struct LogicCallArgs","name":"_args","type":"tuple"}],"name":"submitLogicCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_currentValset","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature[]","name":"_sigs","type":"tuple[]"},{"internalType":"bytes32","name":"_theHash","type":"bytes32"},{"internalType":"uint256","name":"_powerThreshold","type":"uint256"}],"name":"testCheckValidatorSignatures","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_valsetArgs","type":"tuple"},{"internalType":"bytes32","name":"_gravityId","type":"bytes32"}],"name":"testMakeCheckpoint","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_newValset","type":"tuple"},{"components":[{"internalType":"address[]","name":"validators","type":"address[]"},{"internalType":"uint256[]","name":"powers","type":"uint256[]"},{"internalType":"uint256","name":"valsetNonce","type":"uint256"},{"internalType":"uint256","name":"rewardAmount","type":"uint256"},{"internalType":"address","name":"rewardToken","type":"address"}],"internalType":"struct ValsetArgs","name":"_currentValset","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct Signature[]","name":"_sigs","type":"tuple[]"}],"name":"updateValset","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a0604052600060045560016005553480156200001b57600080fd5b5060405162003ac238038062003ac28339810160408190526200003e916200032f565b6001600055805182511415806200005457508151155b15620000735760405163c6617b7b60e01b815260040160405180910390fd5b6000805b8251811015620000d55782818151811062000096576200009662000418565b602002602001015182620000ab919062000444565b915063aaaaaaaa821115620000c057620000d5565b80620000cc816200045f565b91505062000077565b5063aaaaaaaa81116200010b5760405162bfb6ab60e01b81526004810182905263aaaaaaaa602482015260440160405180910390fd5b620001476040518060a001604052806060815260200160608152602001600081526020016000815260200160006001600160a01b031681525090565b506040805160a0810182528481526020810184905260009181018290526060810182905260808101829052906200017f8287620001e1565b6080879052600181905560045460055460405192935090917f76d08978c024a4bf8cbb30c67fd78fcaa1827cbc533e4e175f36d07e64ccf96a91620001cd9160009081908b908b90620004f5565b60405180910390a2505050505050620005a4565b6000806918da1958dadc1bda5b9d60b21b60001b90506000838286604001518760000151886020015189606001518a608001516040516020016200022c979695949392919062000544565b60408051808303601f19018152919052805160209091012095945050505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200028e576200028e6200024d565b604052919050565b60006001600160401b03821115620002b257620002b26200024d565b5060051b60200190565b600082601f830112620002ce57600080fd5b81516020620002e7620002e18362000296565b62000263565b82815260059290921b840181019181810190868411156200030757600080fd5b8286015b848110156200032457805183529183019183016200030b565b509695505050505050565b6000806000606084860312156200034557600080fd5b8351602080860151919450906001600160401b03808211156200036757600080fd5b818701915087601f8301126200037c57600080fd5b81516200038d620002e18262000296565b81815260059190911b8301840190848101908a831115620003ad57600080fd5b938501935b82851015620003e45784516001600160a01b0381168114620003d45760008081fd5b82529385019390850190620003b2565b60408a01519097509450505080831115620003fe57600080fd5b50506200040e86828701620002bc565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082198211156200045a576200045a6200042e565b500190565b60006000198214156200047657620004766200042e565b5060010190565b600081518084526020808501945080840160005b83811015620004b85781516001600160a01b03168752958201959082019060010162000491565b509495945050505050565b600081518084526020808501945080840160005b83811015620004b857815187529582019590820190600101620004d7565b85815284602082015260018060a01b038416604082015260a0606082015260006200052460a08301856200047d565b8281036080840152620005388185620004c3565b98975050505050505050565b87815286602082015285604082015260e0606082015260006200056b60e08301876200047d565b82810360808401526200057f8187620004c3565b60a084019590955250506001600160a01b039190911660c09091015295945050505050565b6080516134ed620005d5600039600081816102140152818161055e015281816105f901526109b501526134ed6000f3fe60806040523480156200001157600080fd5b5060043610620001085760003560e01c80638690ff9811620000a3578063c9d194d5116200006e578063c9d194d51462000236578063df97174b1462000259578063f2b53307146200027c578063f7955637146200028657600080fd5b80638690ff9814620001d6578063aca6b1c114620001ed578063b56561fe1462000204578063bdda81d4146200020e57600080fd5b80630f21235711620000e45780630f212357146200017b5780636941db93146200019257806373b2054714620001a95780637dfb6f8614620001b357600080fd5b8062901153146200010d578063010315251462000126578063011b2174146200013d575b600080fd5b620001246200011e36600462001893565b6200029d565b005b620001246200013736600462001914565b620002b3565b620001696200014e36600462001979565b6001600160a01b031660009081526002602052604090205490565b60405190815260200160405180910390f35b620001246200018c366004620019db565b620002ce565b62000124620001a336600462001c29565b62000490565b6200016960055481565b62000169620001c436600462001dc5565b60036020526000908152604090205481565b62000124620001e736600462001e26565b62000825565b62000124620001fe36600462001f5f565b62000b7a565b6200016960045481565b620001697f000000000000000000000000000000000000000000000000000000000000000081565b620001696200024736600462001dc5565b60009081526003602052604090205490565b620001696200026a36600462001979565b60026020526000908152604090205481565b6200016960015481565b620001246200029736600462002005565b62000e69565b620002ac858585858562000f21565b5050505050565b620002c9620002c283620020bb565b826200107b565b505050565b60026000541415620002fd5760405162461bcd60e51b8152600401620002f49062002171565b60405180910390fd5b600260009081556040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa15801562000349573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200036f9190620021a8565b9050620003886001600160a01b038616333085620010e7565b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015620003d0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003f69190620021a8565b905081811162000419576040516321739d9b60e01b815260040160405180910390fd5b60055462000429906001620021d8565b600555336001600160a01b0387167f9e9794dbf94b0a0aa31a480f5b38550eda7f89115ac8fbf4953fa4dd219900c98787620004668787620021f3565b6005546040516200047b949392919062002236565b60405180910390a35050600160005550505050565b60026000541415620004b65760405162461bcd60e51b8152600401620002f49062002171565b600260005560c08101514310620004e05760405163bcf37c2560e01b815260040160405180910390fd5b61010081015160e0820151600090815260036020526040902054106200053d5761010081015160e082015160009081526003602052604090819020549051629427e960e11b815260048101929092526024820152604401620002f4565b6200054a8484846200115a565b600154620005836200055c86620020bb565b7f00000000000000000000000000000000000000000000000000000000000000006200107b565b14620005a25760405163723a340360e01b815260040160405180910390fd5b60208101515181515114620005ca57604051634298a95160e11b815260040160405180910390fd5b80606001515181604001515114620005f557604051634829247960e01b815260040160405180910390fd5b60007f0000000000000000000000000000000000000000000000000000000000000000681b1bd9da58d0d85b1b60ba1b836000015184602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016200066f9b9a9998979695949392919062002334565b6040516020818303038152906040528051906020012090506200069a8585858463aaaaaaaa62000f21565b5061010081015160e08201516000908152600360205260408120919091555b8151518110156200073d5762000728826080015183600001518381518110620006e657620006e6620023e4565b602002602001015184602001518481518110620007075762000707620023e4565b60200260200101516001600160a01b0316620011b39092919063ffffffff16565b806200073481620023fa565b915050620006b9565b5060006200075482608001518360a00151620011e5565b905060005b826040015151811015620007bb57620007a63384604001518381518110620007855762000785620023e4565b602002602001015185606001518481518110620007075762000707620023e4565b80620007b281620023fa565b91505062000759565b50600554620007cc906001620021d8565b600581905560e08301516101008401516040517f7c2bb24f8e1b3725cb613d7f11ef97d9745cc97a0e40f730621c052d684077a1936200081193929186919062002418565b60405180910390a150506001600055505050565b600260005414156200084b5760405162461bcd60e51b8152600401620002f49062002171565b600260008181556001600160a01b038416815260209190915260409020548311620008af576001600160a01b0382166000908152600260205260409081902054905163f7f920ad60e01b8152620002f4918591600401918252602082015260400190565b6001600160a01b038216600090815260026020526040902054620008d790620f4240620021d8565b8311156200091e576001600160a01b0382166000908152600260205260409081902054905163f7f920ad60e01b8152620002f4918591600401918252602082015260400190565b8043106200093f576040516308b9266360e11b815260040160405180910390fd5b6200094c8c8c8c6200115a565b6001546200095e6200055c8e620020bb565b146200097d5760405163723a340360e01b815260040160405180910390fd5b87861415806200098d5750878414155b15620009ac5760405163c1f97e3560e01b815260040160405180910390fd5b62000a2e8c8c8c7f00000000000000000000000000000000000000000000000000000000000000006f0e8e4c2dce6c2c6e8d2dedc84c2e8c6d60831b8e8e8e8e8e8e8e8e8e60405160200162000a0d9b9a99989796959493929190620024c1565b6040516020818303038152906040528051906020012063aaaaaaaa62000f21565b6001600160a01b0382166000908152600260205260408120849055805b8981101562000afa5762000aba89898381811062000a6d5762000a6d620023e4565b905060200201602081019062000a84919062001979565b8c8c8481811062000a995762000a99620023e4565b90506020020135866001600160a01b0316620011b39092919063ffffffff16565b86868281811062000acf5762000acf620023e4565b905060200201358262000ae39190620021d8565b91508062000af181620023fa565b91505062000a4b565b5062000b116001600160a01b0384163383620011b3565b5060055462000b22906001620021d8565b60058190556040519081526001600160a01b0383169084907f02c7e81975f8edb86e2a0c038b7b86a49c744236abf0f6177ff5afc6986ab7089060200160405180910390a35050600160005550505050505050505050565b826040013584604001351162000bb3576040805163e0e8edf360e01b8152818601356004820152908401356024820152604401620002f4565b62000bc66040840135620f4240620021d8565b8460400135111562000bfb576040805163e0e8edf360e01b8152818601356004820152908401356024820152604401620002f4565b62000c0a60208501856200253f565b905062000c1885806200253f565b905014158062000c33575062000c2f84806200253f565b1590505b1562000c525760405163c01ba0ab60e01b815260040160405180910390fd5b62000c5f8383836200115a565b6000805b62000c7260208701876200253f565b905081101562000cdc5762000c8b60208701876200253f565b8281811062000c9e5762000c9e620023e4565b905060200201358262000cb29190620021d8565b915063aaaaaaaa82111562000cc75762000cdc565b8062000cd381620023fa565b91505062000c63565b5063aaaaaaaa811162000d0f5760405162bfb6ab60e01b81526004810182905263aaaaaaaa6024820152604401620002f4565b60015462000d216200055c86620020bb565b1462000d405760405163723a340360e01b815260040160405180910390fd5b600062000d516200055c87620020bb565b905062000d668585858463aaaaaaaa62000f21565b60018190556040860135600455600062000d8760a088016080890162001979565b6001600160a01b03161415801562000da25750606086013515155b1562000dd55762000dd533606088013562000dc460a08a0160808b0162001979565b6001600160a01b03169190620011b3565b60055462000de5906001620021d8565b60058190556040870135907f76d08978c024a4bf8cbb30c67fd78fcaa1827cbc533e4e175f36d07e64ccf96a90606089013562000e2960a08b0160808c0162001979565b62000e358b806200253f565b62000e4460208e018e6200253f565b60405162000e5997969594939291906200258b565b60405180910390a2505050505050565b600030868686868660405162000e7f906200181e565b62000e9096959493929190620025de565b604051809103906000f08015801562000ead573d6000803e3d6000fd5b509050600554600162000ec19190620021d8565b60058190556040516001600160a01b038316917f82fe3a4fa49c6382d0c085746698ddbbafe6c2bf61285b19410644b5b26287c79162000f0f918c918c918c918c918c918c918c9162002631565b60405180910390a25050505050505050565b6000805b62000f3187806200253f565b9050811015620010475785858281811062000f505762000f50620023e4565b62000f6892602060609092020190810191506200268e565b60ff1615620010325762000fcd62000f8188806200253f565b8381811062000f945762000f94620023e4565b905060200201602081019062000fab919062001979565b8588888581811062000fc15762000fc1620023e4565b90506060020162001230565b62000feb57604051638baa579f60e01b815260040160405180910390fd5b62000ffa60208801886200253f565b828181106200100d576200100d620023e4565b9050602002013582620010219190620021d8565b915082821115620010325762001047565b806200103e81620023fa565b91505062000f25565b50818111620010735760405162bfb6ab60e01b81526004810182905260248101839052604401620002f4565b505050505050565b6000806918da1958dadc1bda5b9d60b21b60001b90506000838286604001518760000151886020015189606001518a60800151604051602001620010c69796959493929190620026ac565b60408051808303601f19018152919052805160209091012095945050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052620011549085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152620012c5565b50505050565b6200116960208401846200253f565b90506200117784806200253f565b9050141580620011945750806200118f84806200253f565b905014155b15620002c95760405163c6617b7b60e01b815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052620002c990849063a9059cbb60e01b906064016200111c565b60606200122983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506200139e565b9392505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018390526000908190605c0160408051601f1981840301815291905280516020918201209150620012a790829062001297908601866200268e565b85602001358660400135620013b7565b6001600160a01b0316856001600160a01b0316149150509392505050565b60006200131c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200139e9092919063ffffffff16565b805190915015620002c957808060200190518101906200133d91906200270c565b620002c95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620002f4565b6060620013af8484600085620013e3565b949350505050565b6000806000620013ca8787878762001515565b91509150620013d9816200160a565b5095945050505050565b606082471015620014465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620002f4565b843b620014965760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620002f4565b600080866001600160a01b03168587604051620014b4919062002730565b60006040518083038185875af1925050503d8060008114620014f3576040519150601f19603f3d011682016040523d82523d6000602084013e620014f8565b606091505b50915091506200150a828286620017e0565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156200154e575060009050600362001601565b8460ff16601b141580156200156757508460ff16601c14155b156200157a575060009050600462001601565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015620015cf573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116620015fa5760006001925092505062001601565b9150600090505b94509492505050565b60008160048111156200162157620016216200274e565b14156200162b5750565b60018160048111156200164257620016426200274e565b1415620016925760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401620002f4565b6002816004811115620016a957620016a96200274e565b1415620016f95760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401620002f4565b60038160048111156200171057620017106200274e565b14156200176b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401620002f4565b60048160048111156200178257620017826200274e565b1415620017dd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401620002f4565b50565b60608315620017f157508162001229565b825115620018025782518084602001fd5b8160405162461bcd60e51b8152600401620002f4919062002764565b610d3e806200277a83390190565b600060a082840312156200183f57600080fd5b50919050565b60008083601f8401126200185857600080fd5b5081356001600160401b038111156200187057600080fd5b6020830191508360206060830285010111156200188c57600080fd5b9250929050565b600080600080600060808688031215620018ac57600080fd5b85356001600160401b0380821115620018c457600080fd5b620018d289838a016200182c565b96506020880135915080821115620018e957600080fd5b50620018f88882890162001845565b9699909850959660408101359660609091013595509350505050565b600080604083850312156200192857600080fd5b82356001600160401b038111156200193f57600080fd5b6200194d858286016200182c565b95602094909401359450505050565b80356001600160a01b03811681146200197457600080fd5b919050565b6000602082840312156200198c57600080fd5b62001229826200195c565b60008083601f840112620019aa57600080fd5b5081356001600160401b03811115620019c257600080fd5b6020830191508360208285010111156200188c57600080fd5b60008060008060608587031215620019f257600080fd5b620019fd856200195c565b935060208501356001600160401b0381111562001a1957600080fd5b62001a278782880162001997565b9598909750949560400135949350505050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b038111828210171562001a765762001a7662001a3a565b60405290565b604051601f8201601f191681016001600160401b038111828210171562001aa75762001aa762001a3a565b604052919050565b60006001600160401b0382111562001acb5762001acb62001a3a565b5060051b60200190565b600082601f83011262001ae757600080fd5b8135602062001b0062001afa8362001aaf565b62001a7c565b82815260059290921b8401810191818101908684111562001b2057600080fd5b8286015b8481101562001b3d578035835291830191830162001b24565b509695505050505050565b600082601f83011262001b5a57600080fd5b8135602062001b6d62001afa8362001aaf565b82815260059290921b8401810191818101908684111562001b8d57600080fd5b8286015b8481101562001b3d5762001ba5816200195c565b835291830191830162001b91565b600082601f83011262001bc557600080fd5b81356001600160401b0381111562001be15762001be162001a3a565b62001bf6601f8201601f191660200162001a7c565b81815284602083860101111562001c0c57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806060858703121562001c4057600080fd5b84356001600160401b038082111562001c5857600080fd5b62001c66888389016200182c565b9550602087013591508082111562001c7d57600080fd5b62001c8b8883890162001845565b9095509350604087013591508082111562001ca557600080fd5b90860190610120828903121562001cbb57600080fd5b62001cc562001a50565b82358281111562001cd557600080fd5b62001ce38a82860162001ad5565b82525060208301358281111562001cf957600080fd5b62001d078a82860162001b48565b60208301525060408301358281111562001d2057600080fd5b62001d2e8a82860162001ad5565b60408301525060608301358281111562001d4757600080fd5b62001d558a82860162001b48565b60608301525062001d69608084016200195c565b608082015260a08301358281111562001d8157600080fd5b62001d8f8a82860162001bb3565b60a08301525060c083013560c082015260e083013560e08201526101009150818301358282015280935050505092959194509250565b60006020828403121562001dd857600080fd5b5035919050565b60008083601f84011262001df257600080fd5b5081356001600160401b0381111562001e0a57600080fd5b6020830191508360208260051b85010111156200188c57600080fd5b6000806000806000806000806000806000806101008d8f03121562001e4a57600080fd5b6001600160401b038d35111562001e6057600080fd5b62001e6f8e8e358f016200182c565b9b506001600160401b0360208e0135111562001e8a57600080fd5b62001e9c8e60208f01358f0162001845565b909b5099506001600160401b0360408e0135111562001eba57600080fd5b62001ecc8e60408f01358f0162001ddf565b90995097506001600160401b0360608e0135111562001eea57600080fd5b62001efc8e60608f01358f0162001ddf565b90975095506001600160401b0360808e0135111562001f1a57600080fd5b62001f2c8e60808f01358f0162001ddf565b909550935060a08d0135925062001f4660c08e016200195c565b915060e08d013590509295989b509295989b509295989b565b6000806000806060858703121562001f7657600080fd5b84356001600160401b038082111562001f8e57600080fd5b62001f9c888389016200182c565b9550602087013591508082111562001fb357600080fd5b62001fc1888389016200182c565b9450604087013591508082111562001fd857600080fd5b5062001fe78782880162001845565b95989497509550505050565b803560ff811681146200197457600080fd5b60008060008060008060006080888a0312156200202157600080fd5b87356001600160401b03808211156200203957600080fd5b620020478b838c0162001997565b909950975060208a01359150808211156200206157600080fd5b6200206f8b838c0162001997565b909750955060408a01359150808211156200208957600080fd5b50620020988a828b0162001997565b9094509250620020ad90506060890162001ff3565b905092959891949750929550565b600060a08236031215620020ce57600080fd5b60405160a081016001600160401b038282108183111715620020f457620020f462001a3a565b8160405284359150808211156200210a57600080fd5b620021183683870162001b48565b835260208501359150808211156200212f57600080fd5b506200213e3682860162001ad5565b602083015250604083013560408201526060830135606082015262002166608084016200195c565b608082015292915050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208284031215620021bb57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115620021ee57620021ee620021c2565b500190565b600082821015620022085762002208620021c2565b500390565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006200224c6060830186886200220d565b6020830194909452506040015292915050565b600081518084526020808501945080840160005b83811015620022915781518752958201959082019060010162002273565b509495945050505050565b600081518084526020808501945080840160005b83811015620022915781516001600160a01b031687529582019590820190600101620022b0565b60005b83811015620022f4578181015183820152602001620022da565b83811115620011545750506000910152565b6000815180845262002320816020860160208601620022d7565b601f01601f19169290920160200192915050565b60006101608d83528c6020840152806040840152620023568184018d6200225f565b905082810360608401526200236c818c6200229c565b9050828103608084015262002382818b6200225f565b905082810360a084015262002398818a6200229c565b6001600160a01b03891660c085015283810360e08501529050620023bd818862002306565b61010084019690965250506101208101929092526101409091015298975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620024115762002411620021c2565b5060010190565b84815283602082015260806040820152600062002439608083018562002306565b905082606083015295945050505050565b81835260006001600160fb1b038311156200246457600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183526000602080850194508260005b8581101562002291576001600160a01b03620024ad836200195c565b168752958201959082019060010162002491565b60006101008d83528c6020840152806040840152620024e48184018c8e6200244a565b90508281036060840152620024fb818a8c62002481565b905082810360808401526200251281888a6200244a565b60a084019690965250506001600160a01b039290921660c083015260e09091015298975050505050505050565b6000808335601e198436030181126200255757600080fd5b8301803591506001600160401b038211156200257257600080fd5b6020019150600581901b36038213156200188c57600080fd5b87815286602082015260018060a01b038616604082015260a060608201526000620025bb60a08301868862002481565b8281036080840152620025d08185876200244a565b9a9950505050505050505050565b6001600160a01b03871681526080602082018190526000906200260590830187896200220d565b82810360408401526200261a8186886200220d565b91505060ff83166060830152979650505050505050565b60a0815260006200264760a083018a8c6200220d565b82810360208401526200265c81898b6200220d565b90508281036040840152620026738187896200220d565b60ff9590951660608401525050608001529695505050505050565b600060208284031215620026a157600080fd5b620012298262001ff3565b87815286602082015285604082015260e060608201526000620026d360e08301876200229c565b8281036080840152620026e781876200225f565b60a084019590955250506001600160a01b039190911660c09091015295945050505050565b6000602082840312156200271f57600080fd5b815180151581146200122957600080fd5b6000825162002744818460208701620022d7565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b6020815260006200122960208301846200230656fe60806040526000196005553480156200001757600080fd5b5060405162000d3e38038062000d3e8339810160408190526200003a9162000307565b8251839083906200005390600390602085019062000194565b5080516200006990600490602084019062000194565b5050600680546001600160a01b038716610100026001600160a81b031990911660ff85161717905550600554620000a2908590620000ac565b505050506200040f565b6001600160a01b038216620001075760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b80600260008282546200011b9190620003ab565b90915550506001600160a01b038216600090815260208190526040812080548392906200014a908490620003ab565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b828054620001a290620003d2565b90600052602060002090601f016020900481019282620001c6576000855562000211565b82601f10620001e157805160ff191683800117855562000211565b8280016001018555821562000211579182015b8281111562000211578251825591602001919060010190620001f4565b506200021f92915062000223565b5090565b5b808211156200021f576000815560010162000224565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200026257600080fd5b81516001600160401b03808211156200027f576200027f6200023a565b604051601f8301601f19908116603f01168101908282118183101715620002aa57620002aa6200023a565b81604052838152602092508683858801011115620002c757600080fd5b600091505b83821015620002eb5785820183015181830184015290820190620002cc565b83821115620002fd5760008385830101525b9695505050505050565b600080600080608085870312156200031e57600080fd5b84516001600160a01b03811681146200033657600080fd5b60208601519094506001600160401b03808211156200035457600080fd5b620003628883890162000250565b945060408701519150808211156200037957600080fd5b50620003888782880162000250565b925050606085015160ff81168114620003a057600080fd5b939692955090935050565b60008219821115620003cd57634e487b7160e01b600052601160045260246000fd5b500190565b600181811c90821680620003e757607f821691505b602082108114156200040957634e487b7160e01b600052602260045260246000fd5b50919050565b61091f806200041f6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461012d57806370a082311461014057806395d89b4114610169578063a457c2d714610171578063a9059cbb14610184578063dd62ed3e1461019757600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610105578063313ce56714610118575b600080fd5b6100b66101d0565b6040516100c3919061073d565b60405180910390f35b6100df6100da3660046107ae565b610262565b60405190151581526020016100c3565b6100f7610278565b6040519081526020016100c3565b6100df6101133660046107d8565b6102aa565b60065460405160ff90911681526020016100c3565b6100df61013b3660046107ae565b610359565b6100f761014e366004610814565b6001600160a01b031660009081526020819052604090205490565b6100b6610395565b6100df61017f3660046107ae565b6103a4565b6100df6101923660046107ae565b61043d565b6100f76101a5366004610836565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600380546101df90610869565b80601f016020809104026020016040519081016040528092919081815260200182805461020b90610869565b80156102585780601f1061022d57610100808354040283529160200191610258565b820191906000526020600020905b81548152906001019060200180831161023b57829003601f168201915b5050505050905090565b600061026f33848461044a565b50600192915050565b60065461010090046001600160a01b03166000908152602081905260408120546005546102a591906108ba565b905090565b60006102b784848461056e565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156103415760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61034e853385840361044a565b506001949350505050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161026f9185906103909086906108d1565b61044a565b6060600480546101df90610869565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156104265760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610338565b610433338585840361044a565b5060019392505050565b600061026f33848461056e565b6001600160a01b0383166104ac5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610338565b6001600160a01b03821661050d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610338565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166105d25760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610338565b6001600160a01b0382166106345760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610338565b6001600160a01b038316600090815260208190526040902054818110156106ac5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610338565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906106e39084906108d1565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161072f91815260200190565b60405180910390a350505050565b600060208083528351808285015260005b8181101561076a5785810183015185820160400152820161074e565b8181111561077c576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146107a957600080fd5b919050565b600080604083850312156107c157600080fd5b6107ca83610792565b946020939093013593505050565b6000806000606084860312156107ed57600080fd5b6107f684610792565b925061080460208501610792565b9150604084013590509250925092565b60006020828403121561082657600080fd5b61082f82610792565b9392505050565b6000806040838503121561084957600080fd5b61085283610792565b915061086060208401610792565b90509250929050565b600181811c9082168061087d57607f821691505b6020821081141561089e57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156108cc576108cc6108a4565b500390565b600082198211156108e4576108e46108a4565b50019056fea264697066735822122030a282fb7e0b734096beb9323062edce33d11c6ccd7166512f1150282b9d8c8a64736f6c634300080a0033a2646970667358221220a343e67087c843940f5d01cf08cc6bb77beecfc24ee508b7d14cc759a0d3b10564736f6c634300080a0033677261766974792d6272696467652d6d61696e6e65740000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000062000000000000000000000000d02ec8a3fa36cad9d0e6c57b2b8dac9c919bf47e000000000000000000000000d06615eb94920948fededf59e012f688274db5270000000000000000000000001346d2b524c7f8d5549d5f3e87cce3904aa9b4cb000000000000000000000000bdadee22baf8ea072351ef197f48a76c3c18261a000000000000000000000000f6558340163774cc70b38bc1480e21065b0adde80000000000000000000000002c9df7dbe6e73f0b2a1045d1ae608a5230915fee000000000000000000000000042d9cdd6548b51456115000a777f3c59569d99700000000000000000000000011ea1cf1dd5fd9315d45cb6c15e901cb5159d8bb000000000000000000000000fd272eab659160c9ed5a89296a0ca21d28766b6d000000000000000000000000def65f9f0caef14616e2f2ed1945b68ad66562750000000000000000000000003e8ebde4324526ed7119ebc557886b84f9e92c0a0000000000000000000000006299a50d80549dfc758b335e174a2bfac81d6c62000000000000000000000000ac6d6d4ecdeb8d1174e1d948f71f0ba0c331ff920000000000000000000000008f7d963b5402bf073a67ba800b98d788213367c4000000000000000000000000a7298bc2025623626fe139ac65443112a9964953000000000000000000000000659b31cf9b3eff48aaa2f69a29cd96b331a5dde2000000000000000000000000e7b73fa6b0965faf3ec97efa884e7dd6d741e8bb0000000000000000000000002e5c835adb3f9561ded370bd8ad06a8306254f03000000000000000000000000026504d0c32a99205de5af38875864ede58a746f000000000000000000000000af15575b8cfee665a215606a76313fce2eeb5aa90000000000000000000000007beb98a706033fa28b22098a160974c270325da2000000000000000000000000f08506576345fb6abb6a80fcec2d34e4c547c8060000000000000000000000000c84b0299018757c8a94cad699800b68856acbab00000000000000000000000006a49340adeabbbea0b850c581cd07c5a1e57c47000000000000000000000000eb529af497f6736ed9eeb2749edc6c38658f32cf0000000000000000000000006259523bc13e1e3ec964d3cdf9da9517958804cb000000000000000000000000c16e3b44b0779d4b183a581055c7fef55ed25519000000000000000000000000048de1810eee92d2c540125c9a4896ea5c064c67000000000000000000000000049796a46ad4e24e6feea4f836b56c407484b52c000000000000000000000000097ee4acab904d9b477e4fc49c7e1ea67b460bc90000000000000000000000001864f0c868eedcc541391dbcf95028bed3dfbe590000000000000000000000001a055371f135c350df98d43be53a71d719f987d90000000000000000000000001d039a919efb8d88e5c24d8011c1581beaa4e8c30000000000000000000000001bcc53de17f04151865912e29173105653727cff00000000000000000000000020f604dc5a3d49b93b21bd40227f43dc37b3106e00000000000000000000000021872c12b1bab85607399b2ee36be75116d708a400000000000000000000000023f91f6a4d0d33d0a48c0728b5f4fb51d4c85edb000000000000000000000000290515f2a26f70c34daf51448c983d3931ea352b0000000000000000000000002982ceaba98bab8ec05a067ffe3a1c2ec3c610c30000000000000000000000002e28d0fc5fd9a0eb807f9c3ea1a0aa43ad7da86c0000000000000000000000002ba80daad13b74ff72dab650fc55a8df343190f20000000000000000000000002c0c794c54a2f6fb37a636da651f00c19497d6ce00000000000000000000000031c32051fca40b133cf9970cfaf141c11ec32512000000000000000000000000366fb970995e737a7b6eb8be8c46b0a5f6392aa100000000000000000000000038a838a8783d5f47b09d28c5c5107e72b880669e0000000000000000000000003d38ca4e28d3e60c16aeaf5617a32a0682211a940000000000000000000000004902d2683cc0123c1fea82ebc361a8f58fb8305500000000000000000000000052173e859a91551a383b3bc96d40d73114ff038700000000000000000000000052511a2b60cfd6e1fb0af37b7ba0a1d8ef82b0ca00000000000000000000000053093609e41632ade1108d22c98e7a90c9e51101000000000000000000000000532a1deebc5c54ec93627866cfc9007be2f6181300000000000000000000000054848e2870925d2a0df158feb10a9f99c45f8f3d000000000000000000000000577de4619f91d8fd5e434af791318a45db166d370000000000000000000000005b390b4256279dbdd9b699853edd787a97975a4d0000000000000000000000005c1522670a750d548ce767eba332d09e171a196d0000000000000000000000005deb18a724df51902e0742d7477340ab80fe611c000000000000000000000000624977fe6a9f887fa858957b3b92b39423b43b3200000000000000000000000063e37e48f29f1b2aca247e045d6244309cba577e000000000000000000000000646f836b0a88a7a1dc2dfddee260b4c86a583fa40000000000000000000000006b1dfe7ca2e93b6a0b534d140b02054deaa834490000000000000000000000007960c3c30718f9f99137956646763146736802340000000000000000000000007baa546a8af98076e0ff868730f1c30a50a0a7f20000000000000000000000007e33410db54e9eadf619911b2e4d404fa08a7f3d0000000000000000000000007f96379a0f136176270f382b37c6215b2f25790300000000000000000000000082a2ef1df41bdec4292ddbf8fca870ca40a253cd00000000000000000000000082b72ce9b848b91d3943867eca064bc4b3504a8f00000000000000000000000083377eb59ffbf333179d241457e4efdbdb9f7bc10000000000000000000000008477bf7c6d465405a840570a405a2973d9dc8d520000000000000000000000008f8011fda21d25d9c4846790d6ef66c8398cc3b50000000000000000000000008be231e6ed8e002cac60ca2284e6ef377c188eca0000000000000000000000009384803b6a8f07b13691e40747933c09b6c5635600000000000000000000000098f99515c0a44eb4f45f33bd41eea304da13e4000000000000000000000000009f7bbb1f313e8bc7309ab6be429ebf1df0fd54fe000000000000000000000000a17e673d399308aa4f6f80065e484058b1bc69c3000000000000000000000000be365629ced317dd785328a0c4425dd1be1c6f8c000000000000000000000000caa8b3e3bf2385c74041a96b6599560e68808a46000000000000000000000000dca8c176c2610adc07e84b008cc5b6dbbcce7236000000000000000000000000db6b96055156908d1263796ce559cccacdef3d7b000000000000000000000000de328ee7b3a6e3918a54ea8765d09e841ad5f56a000000000000000000000000e20d2fda099815b5b7724712d39b97daacb4b855000000000000000000000000a61889a82f66a9286075e2bf3984e49df28a9a11000000000000000000000000b1d6785e38ba13a35e479222dab48e083b18a282000000000000000000000000b3261b22e3fd1715ec639b1a8f1edea8ed3163dd000000000000000000000000b9d03c913e368a0137b2d08d75263525ad3fccfc000000000000000000000000bc3f6a075c931ce5d9d6a20d8ee652d940cf5b7a000000000000000000000000c0043256d85d56194fe50e83bc819c4dcb1d9a97000000000000000000000000c20f0557cf68ed2ea1227473960fcb532a0f430b000000000000000000000000c6de773e6f30155f55468e0b3ddb612904225597000000000000000000000000cebfd2dd7b42032582fccd2b6a9bba88a2e4ebf0000000000000000000000000d059ee08dacf95c91940515aec6353bdcd587929000000000000000000000000d5bc4fea09f514a1c86ba06dad51aeb8edefdd34000000000000000000000000d9bc82708848dca0eccb6d51712185da2a8cadee000000000000000000000000e0fbe446c1fb21f42aa41f9edcf8a6611c86d419000000000000000000000000ef2403fe087a250697d9d93709466bf51d228188000000000000000000000000eb60b3c0ed0c75a4ed52d27a7f505e596afa9e3e000000000000000000000000ee320c1e727bc617545a8ae09e71b85dbef7a8e4000000000000000000000000f65615165d3520a4b804a7710f17a687a2164c79000000000000000000000000fa42a24df34df089413e9aceb162b7c8f02131f90000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000002344dc27000000000000000000000000000000000000000000000000000000000246b8a9000000000000000000000000000000000000000000000000000000000246b561000000000000000000000000000000000000000000000000000000000246b48f000000000000000000000000000000000000000000000000000000000246b48f000000000000000000000000000000000000000000000000000000000246b3bd000000000000000000000000000000000000000000000000000000000246b2eb000000000000000000000000000000000000000000000000000000000246b2eb000000000000000000000000000000000000000000000000000000000246b2eb000000000000000000000000000000000000000000000000000000000246b147000000000000000000000000000000000000000000000000000000000246b075000000000000000000000000000000000000000000000000000000000246b075000000000000000000000000000000000000000000000000000000000246b075000000000000000000000000000000000000000000000000000000000246aed1000000000000000000000000000000000000000000000000000000000246ad2d000000000000000000000000000000000000000000000000000000000246ac5b000000000000000000000000000000000000000000000000000000000246a9e6000000000000000000000000000000000000000000000000000000000246a914000000000000000000000000000000000000000000000000000000000246a428000000000000000000000000000000000000000000000000000000000246a0e0000000000000000000000000000000000000000000000000000000000246a00e0000000000000000000000000000000000000000000000000000000002469e6a0000000000000000000000000000000000000000000000000000000002469b220000000000000000000000000000000000000000000000000000000002469636000000000000000000000000000000000000000000000000000000000246949300000000000000000000000000000000000000000000000000000000024693c10000000000000000000000000000000000000000000000000000000002468b8d00000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b5

Deployed Bytecode

0x60806040523480156200001157600080fd5b5060043610620001085760003560e01c80638690ff9811620000a3578063c9d194d5116200006e578063c9d194d51462000236578063df97174b1462000259578063f2b53307146200027c578063f7955637146200028657600080fd5b80638690ff9814620001d6578063aca6b1c114620001ed578063b56561fe1462000204578063bdda81d4146200020e57600080fd5b80630f21235711620000e45780630f212357146200017b5780636941db93146200019257806373b2054714620001a95780637dfb6f8614620001b357600080fd5b8062901153146200010d578063010315251462000126578063011b2174146200013d575b600080fd5b620001246200011e36600462001893565b6200029d565b005b620001246200013736600462001914565b620002b3565b620001696200014e36600462001979565b6001600160a01b031660009081526002602052604090205490565b60405190815260200160405180910390f35b620001246200018c366004620019db565b620002ce565b62000124620001a336600462001c29565b62000490565b6200016960055481565b62000169620001c436600462001dc5565b60036020526000908152604090205481565b62000124620001e736600462001e26565b62000825565b62000124620001fe36600462001f5f565b62000b7a565b6200016960045481565b620001697f677261766974792d6272696467652d6d61696e6e65740000000000000000000081565b620001696200024736600462001dc5565b60009081526003602052604090205490565b620001696200026a36600462001979565b60026020526000908152604090205481565b6200016960015481565b620001246200029736600462002005565b62000e69565b620002ac858585858562000f21565b5050505050565b620002c9620002c283620020bb565b826200107b565b505050565b60026000541415620002fd5760405162461bcd60e51b8152600401620002f49062002171565b60405180910390fd5b600260009081556040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa15801562000349573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200036f9190620021a8565b9050620003886001600160a01b038616333085620010e7565b6040516370a0823160e01b81523060048201526000906001600160a01b038716906370a0823190602401602060405180830381865afa158015620003d0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003f69190620021a8565b905081811162000419576040516321739d9b60e01b815260040160405180910390fd5b60055462000429906001620021d8565b600555336001600160a01b0387167f9e9794dbf94b0a0aa31a480f5b38550eda7f89115ac8fbf4953fa4dd219900c98787620004668787620021f3565b6005546040516200047b949392919062002236565b60405180910390a35050600160005550505050565b60026000541415620004b65760405162461bcd60e51b8152600401620002f49062002171565b600260005560c08101514310620004e05760405163bcf37c2560e01b815260040160405180910390fd5b61010081015160e0820151600090815260036020526040902054106200053d5761010081015160e082015160009081526003602052604090819020549051629427e960e11b815260048101929092526024820152604401620002f4565b6200054a8484846200115a565b600154620005836200055c86620020bb565b7f677261766974792d6272696467652d6d61696e6e6574000000000000000000006200107b565b14620005a25760405163723a340360e01b815260040160405180910390fd5b60208101515181515114620005ca57604051634298a95160e11b815260040160405180910390fd5b80606001515181604001515114620005f557604051634829247960e01b815260040160405180910390fd5b60007f677261766974792d6272696467652d6d61696e6e657400000000000000000000681b1bd9da58d0d85b1b60ba1b836000015184602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016200066f9b9a9998979695949392919062002334565b6040516020818303038152906040528051906020012090506200069a8585858463aaaaaaaa62000f21565b5061010081015160e08201516000908152600360205260408120919091555b8151518110156200073d5762000728826080015183600001518381518110620006e657620006e6620023e4565b602002602001015184602001518481518110620007075762000707620023e4565b60200260200101516001600160a01b0316620011b39092919063ffffffff16565b806200073481620023fa565b915050620006b9565b5060006200075482608001518360a00151620011e5565b905060005b826040015151811015620007bb57620007a63384604001518381518110620007855762000785620023e4565b602002602001015185606001518481518110620007075762000707620023e4565b80620007b281620023fa565b91505062000759565b50600554620007cc906001620021d8565b600581905560e08301516101008401516040517f7c2bb24f8e1b3725cb613d7f11ef97d9745cc97a0e40f730621c052d684077a1936200081193929186919062002418565b60405180910390a150506001600055505050565b600260005414156200084b5760405162461bcd60e51b8152600401620002f49062002171565b600260008181556001600160a01b038416815260209190915260409020548311620008af576001600160a01b0382166000908152600260205260409081902054905163f7f920ad60e01b8152620002f4918591600401918252602082015260400190565b6001600160a01b038216600090815260026020526040902054620008d790620f4240620021d8565b8311156200091e576001600160a01b0382166000908152600260205260409081902054905163f7f920ad60e01b8152620002f4918591600401918252602082015260400190565b8043106200093f576040516308b9266360e11b815260040160405180910390fd5b6200094c8c8c8c6200115a565b6001546200095e6200055c8e620020bb565b146200097d5760405163723a340360e01b815260040160405180910390fd5b87861415806200098d5750878414155b15620009ac5760405163c1f97e3560e01b815260040160405180910390fd5b62000a2e8c8c8c7f677261766974792d6272696467652d6d61696e6e6574000000000000000000006f0e8e4c2dce6c2c6e8d2dedc84c2e8c6d60831b8e8e8e8e8e8e8e8e8e60405160200162000a0d9b9a99989796959493929190620024c1565b6040516020818303038152906040528051906020012063aaaaaaaa62000f21565b6001600160a01b0382166000908152600260205260408120849055805b8981101562000afa5762000aba89898381811062000a6d5762000a6d620023e4565b905060200201602081019062000a84919062001979565b8c8c8481811062000a995762000a99620023e4565b90506020020135866001600160a01b0316620011b39092919063ffffffff16565b86868281811062000acf5762000acf620023e4565b905060200201358262000ae39190620021d8565b91508062000af181620023fa565b91505062000a4b565b5062000b116001600160a01b0384163383620011b3565b5060055462000b22906001620021d8565b60058190556040519081526001600160a01b0383169084907f02c7e81975f8edb86e2a0c038b7b86a49c744236abf0f6177ff5afc6986ab7089060200160405180910390a35050600160005550505050505050505050565b826040013584604001351162000bb3576040805163e0e8edf360e01b8152818601356004820152908401356024820152604401620002f4565b62000bc66040840135620f4240620021d8565b8460400135111562000bfb576040805163e0e8edf360e01b8152818601356004820152908401356024820152604401620002f4565b62000c0a60208501856200253f565b905062000c1885806200253f565b905014158062000c33575062000c2f84806200253f565b1590505b1562000c525760405163c01ba0ab60e01b815260040160405180910390fd5b62000c5f8383836200115a565b6000805b62000c7260208701876200253f565b905081101562000cdc5762000c8b60208701876200253f565b8281811062000c9e5762000c9e620023e4565b905060200201358262000cb29190620021d8565b915063aaaaaaaa82111562000cc75762000cdc565b8062000cd381620023fa565b91505062000c63565b5063aaaaaaaa811162000d0f5760405162bfb6ab60e01b81526004810182905263aaaaaaaa6024820152604401620002f4565b60015462000d216200055c86620020bb565b1462000d405760405163723a340360e01b815260040160405180910390fd5b600062000d516200055c87620020bb565b905062000d668585858463aaaaaaaa62000f21565b60018190556040860135600455600062000d8760a088016080890162001979565b6001600160a01b03161415801562000da25750606086013515155b1562000dd55762000dd533606088013562000dc460a08a0160808b0162001979565b6001600160a01b03169190620011b3565b60055462000de5906001620021d8565b60058190556040870135907f76d08978c024a4bf8cbb30c67fd78fcaa1827cbc533e4e175f36d07e64ccf96a90606089013562000e2960a08b0160808c0162001979565b62000e358b806200253f565b62000e4460208e018e6200253f565b60405162000e5997969594939291906200258b565b60405180910390a2505050505050565b600030868686868660405162000e7f906200181e565b62000e9096959493929190620025de565b604051809103906000f08015801562000ead573d6000803e3d6000fd5b509050600554600162000ec19190620021d8565b60058190556040516001600160a01b038316917f82fe3a4fa49c6382d0c085746698ddbbafe6c2bf61285b19410644b5b26287c79162000f0f918c918c918c918c918c918c918c9162002631565b60405180910390a25050505050505050565b6000805b62000f3187806200253f565b9050811015620010475785858281811062000f505762000f50620023e4565b62000f6892602060609092020190810191506200268e565b60ff1615620010325762000fcd62000f8188806200253f565b8381811062000f945762000f94620023e4565b905060200201602081019062000fab919062001979565b8588888581811062000fc15762000fc1620023e4565b90506060020162001230565b62000feb57604051638baa579f60e01b815260040160405180910390fd5b62000ffa60208801886200253f565b828181106200100d576200100d620023e4565b9050602002013582620010219190620021d8565b915082821115620010325762001047565b806200103e81620023fa565b91505062000f25565b50818111620010735760405162bfb6ab60e01b81526004810182905260248101839052604401620002f4565b505050505050565b6000806918da1958dadc1bda5b9d60b21b60001b90506000838286604001518760000151886020015189606001518a60800151604051602001620010c69796959493929190620026ac565b60408051808303601f19018152919052805160209091012095945050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052620011549085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152620012c5565b50505050565b6200116960208401846200253f565b90506200117784806200253f565b9050141580620011945750806200118f84806200253f565b905014155b15620002c95760405163c6617b7b60e01b815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052620002c990849063a9059cbb60e01b906064016200111c565b60606200122983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c656400008152506200139e565b9392505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018390526000908190605c0160408051601f1981840301815291905280516020918201209150620012a790829062001297908601866200268e565b85602001358660400135620013b7565b6001600160a01b0316856001600160a01b0316149150509392505050565b60006200131c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200139e9092919063ffffffff16565b805190915015620002c957808060200190518101906200133d91906200270c565b620002c95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620002f4565b6060620013af8484600085620013e3565b949350505050565b6000806000620013ca8787878762001515565b91509150620013d9816200160a565b5095945050505050565b606082471015620014465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620002f4565b843b620014965760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620002f4565b600080866001600160a01b03168587604051620014b4919062002730565b60006040518083038185875af1925050503d8060008114620014f3576040519150601f19603f3d011682016040523d82523d6000602084013e620014f8565b606091505b50915091506200150a828286620017e0565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156200154e575060009050600362001601565b8460ff16601b141580156200156757508460ff16601c14155b156200157a575060009050600462001601565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015620015cf573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116620015fa5760006001925092505062001601565b9150600090505b94509492505050565b60008160048111156200162157620016216200274e565b14156200162b5750565b60018160048111156200164257620016426200274e565b1415620016925760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401620002f4565b6002816004811115620016a957620016a96200274e565b1415620016f95760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401620002f4565b60038160048111156200171057620017106200274e565b14156200176b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401620002f4565b60048160048111156200178257620017826200274e565b1415620017dd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401620002f4565b50565b60608315620017f157508162001229565b825115620018025782518084602001fd5b8160405162461bcd60e51b8152600401620002f4919062002764565b610d3e806200277a83390190565b600060a082840312156200183f57600080fd5b50919050565b60008083601f8401126200185857600080fd5b5081356001600160401b038111156200187057600080fd5b6020830191508360206060830285010111156200188c57600080fd5b9250929050565b600080600080600060808688031215620018ac57600080fd5b85356001600160401b0380821115620018c457600080fd5b620018d289838a016200182c565b96506020880135915080821115620018e957600080fd5b50620018f88882890162001845565b9699909850959660408101359660609091013595509350505050565b600080604083850312156200192857600080fd5b82356001600160401b038111156200193f57600080fd5b6200194d858286016200182c565b95602094909401359450505050565b80356001600160a01b03811681146200197457600080fd5b919050565b6000602082840312156200198c57600080fd5b62001229826200195c565b60008083601f840112620019aa57600080fd5b5081356001600160401b03811115620019c257600080fd5b6020830191508360208285010111156200188c57600080fd5b60008060008060608587031215620019f257600080fd5b620019fd856200195c565b935060208501356001600160401b0381111562001a1957600080fd5b62001a278782880162001997565b9598909750949560400135949350505050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b038111828210171562001a765762001a7662001a3a565b60405290565b604051601f8201601f191681016001600160401b038111828210171562001aa75762001aa762001a3a565b604052919050565b60006001600160401b0382111562001acb5762001acb62001a3a565b5060051b60200190565b600082601f83011262001ae757600080fd5b8135602062001b0062001afa8362001aaf565b62001a7c565b82815260059290921b8401810191818101908684111562001b2057600080fd5b8286015b8481101562001b3d578035835291830191830162001b24565b509695505050505050565b600082601f83011262001b5a57600080fd5b8135602062001b6d62001afa8362001aaf565b82815260059290921b8401810191818101908684111562001b8d57600080fd5b8286015b8481101562001b3d5762001ba5816200195c565b835291830191830162001b91565b600082601f83011262001bc557600080fd5b81356001600160401b0381111562001be15762001be162001a3a565b62001bf6601f8201601f191660200162001a7c565b81815284602083860101111562001c0c57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806060858703121562001c4057600080fd5b84356001600160401b038082111562001c5857600080fd5b62001c66888389016200182c565b9550602087013591508082111562001c7d57600080fd5b62001c8b8883890162001845565b9095509350604087013591508082111562001ca557600080fd5b90860190610120828903121562001cbb57600080fd5b62001cc562001a50565b82358281111562001cd557600080fd5b62001ce38a82860162001ad5565b82525060208301358281111562001cf957600080fd5b62001d078a82860162001b48565b60208301525060408301358281111562001d2057600080fd5b62001d2e8a82860162001ad5565b60408301525060608301358281111562001d4757600080fd5b62001d558a82860162001b48565b60608301525062001d69608084016200195c565b608082015260a08301358281111562001d8157600080fd5b62001d8f8a82860162001bb3565b60a08301525060c083013560c082015260e083013560e08201526101009150818301358282015280935050505092959194509250565b60006020828403121562001dd857600080fd5b5035919050565b60008083601f84011262001df257600080fd5b5081356001600160401b0381111562001e0a57600080fd5b6020830191508360208260051b85010111156200188c57600080fd5b6000806000806000806000806000806000806101008d8f03121562001e4a57600080fd5b6001600160401b038d35111562001e6057600080fd5b62001e6f8e8e358f016200182c565b9b506001600160401b0360208e0135111562001e8a57600080fd5b62001e9c8e60208f01358f0162001845565b909b5099506001600160401b0360408e0135111562001eba57600080fd5b62001ecc8e60408f01358f0162001ddf565b90995097506001600160401b0360608e0135111562001eea57600080fd5b62001efc8e60608f01358f0162001ddf565b90975095506001600160401b0360808e0135111562001f1a57600080fd5b62001f2c8e60808f01358f0162001ddf565b909550935060a08d0135925062001f4660c08e016200195c565b915060e08d013590509295989b509295989b509295989b565b6000806000806060858703121562001f7657600080fd5b84356001600160401b038082111562001f8e57600080fd5b62001f9c888389016200182c565b9550602087013591508082111562001fb357600080fd5b62001fc1888389016200182c565b9450604087013591508082111562001fd857600080fd5b5062001fe78782880162001845565b95989497509550505050565b803560ff811681146200197457600080fd5b60008060008060008060006080888a0312156200202157600080fd5b87356001600160401b03808211156200203957600080fd5b620020478b838c0162001997565b909950975060208a01359150808211156200206157600080fd5b6200206f8b838c0162001997565b909750955060408a01359150808211156200208957600080fd5b50620020988a828b0162001997565b9094509250620020ad90506060890162001ff3565b905092959891949750929550565b600060a08236031215620020ce57600080fd5b60405160a081016001600160401b038282108183111715620020f457620020f462001a3a565b8160405284359150808211156200210a57600080fd5b620021183683870162001b48565b835260208501359150808211156200212f57600080fd5b506200213e3682860162001ad5565b602083015250604083013560408201526060830135606082015262002166608084016200195c565b608082015292915050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b600060208284031215620021bb57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115620021ee57620021ee620021c2565b500190565b600082821015620022085762002208620021c2565b500390565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006200224c6060830186886200220d565b6020830194909452506040015292915050565b600081518084526020808501945080840160005b83811015620022915781518752958201959082019060010162002273565b509495945050505050565b600081518084526020808501945080840160005b83811015620022915781516001600160a01b031687529582019590820190600101620022b0565b60005b83811015620022f4578181015183820152602001620022da565b83811115620011545750506000910152565b6000815180845262002320816020860160208601620022d7565b601f01601f19169290920160200192915050565b60006101608d83528c6020840152806040840152620023568184018d6200225f565b905082810360608401526200236c818c6200229c565b9050828103608084015262002382818b6200225f565b905082810360a084015262002398818a6200229c565b6001600160a01b03891660c085015283810360e08501529050620023bd818862002306565b61010084019690965250506101208101929092526101409091015298975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415620024115762002411620021c2565b5060010190565b84815283602082015260806040820152600062002439608083018562002306565b905082606083015295945050505050565b81835260006001600160fb1b038311156200246457600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183526000602080850194508260005b8581101562002291576001600160a01b03620024ad836200195c565b168752958201959082019060010162002491565b60006101008d83528c6020840152806040840152620024e48184018c8e6200244a565b90508281036060840152620024fb818a8c62002481565b905082810360808401526200251281888a6200244a565b60a084019690965250506001600160a01b039290921660c083015260e09091015298975050505050505050565b6000808335601e198436030181126200255757600080fd5b8301803591506001600160401b038211156200257257600080fd5b6020019150600581901b36038213156200188c57600080fd5b87815286602082015260018060a01b038616604082015260a060608201526000620025bb60a08301868862002481565b8281036080840152620025d08185876200244a565b9a9950505050505050505050565b6001600160a01b03871681526080602082018190526000906200260590830187896200220d565b82810360408401526200261a8186886200220d565b91505060ff83166060830152979650505050505050565b60a0815260006200264760a083018a8c6200220d565b82810360208401526200265c81898b6200220d565b90508281036040840152620026738187896200220d565b60ff9590951660608401525050608001529695505050505050565b600060208284031215620026a157600080fd5b620012298262001ff3565b87815286602082015285604082015260e060608201526000620026d360e08301876200229c565b8281036080840152620026e781876200225f565b60a084019590955250506001600160a01b039190911660c09091015295945050505050565b6000602082840312156200271f57600080fd5b815180151581146200122957600080fd5b6000825162002744818460208701620022d7565b9190910192915050565b634e487b7160e01b600052602160045260246000fd5b6020815260006200122960208301846200230656fe60806040526000196005553480156200001757600080fd5b5060405162000d3e38038062000d3e8339810160408190526200003a9162000307565b8251839083906200005390600390602085019062000194565b5080516200006990600490602084019062000194565b5050600680546001600160a01b038716610100026001600160a81b031990911660ff85161717905550600554620000a2908590620000ac565b505050506200040f565b6001600160a01b038216620001075760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b80600260008282546200011b9190620003ab565b90915550506001600160a01b038216600090815260208190526040812080548392906200014a908490620003ab565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b828054620001a290620003d2565b90600052602060002090601f016020900481019282620001c6576000855562000211565b82601f10620001e157805160ff191683800117855562000211565b8280016001018555821562000211579182015b8281111562000211578251825591602001919060010190620001f4565b506200021f92915062000223565b5090565b5b808211156200021f576000815560010162000224565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200026257600080fd5b81516001600160401b03808211156200027f576200027f6200023a565b604051601f8301601f19908116603f01168101908282118183101715620002aa57620002aa6200023a565b81604052838152602092508683858801011115620002c757600080fd5b600091505b83821015620002eb5785820183015181830184015290820190620002cc565b83821115620002fd5760008385830101525b9695505050505050565b600080600080608085870312156200031e57600080fd5b84516001600160a01b03811681146200033657600080fd5b60208601519094506001600160401b03808211156200035457600080fd5b620003628883890162000250565b945060408701519150808211156200037957600080fd5b50620003888782880162000250565b925050606085015160ff81168114620003a057600080fd5b939692955090935050565b60008219821115620003cd57634e487b7160e01b600052601160045260246000fd5b500190565b600181811c90821680620003e757607f821691505b602082108114156200040957634e487b7160e01b600052602260045260246000fd5b50919050565b61091f806200041f6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461012d57806370a082311461014057806395d89b4114610169578063a457c2d714610171578063a9059cbb14610184578063dd62ed3e1461019757600080fd5b806306fdde03146100ae578063095ea7b3146100cc57806318160ddd146100ef57806323b872dd14610105578063313ce56714610118575b600080fd5b6100b66101d0565b6040516100c3919061073d565b60405180910390f35b6100df6100da3660046107ae565b610262565b60405190151581526020016100c3565b6100f7610278565b6040519081526020016100c3565b6100df6101133660046107d8565b6102aa565b60065460405160ff90911681526020016100c3565b6100df61013b3660046107ae565b610359565b6100f761014e366004610814565b6001600160a01b031660009081526020819052604090205490565b6100b6610395565b6100df61017f3660046107ae565b6103a4565b6100df6101923660046107ae565b61043d565b6100f76101a5366004610836565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6060600380546101df90610869565b80601f016020809104026020016040519081016040528092919081815260200182805461020b90610869565b80156102585780601f1061022d57610100808354040283529160200191610258565b820191906000526020600020905b81548152906001019060200180831161023b57829003601f168201915b5050505050905090565b600061026f33848461044a565b50600192915050565b60065461010090046001600160a01b03166000908152602081905260408120546005546102a591906108ba565b905090565b60006102b784848461056e565b6001600160a01b0384166000908152600160209081526040808320338452909152902054828110156103415760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b61034e853385840361044a565b506001949350505050565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909161026f9185906103909086906108d1565b61044a565b6060600480546101df90610869565b3360009081526001602090815260408083206001600160a01b0386168452909152812054828110156104265760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610338565b610433338585840361044a565b5060019392505050565b600061026f33848461056e565b6001600160a01b0383166104ac5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610338565b6001600160a01b03821661050d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610338565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166105d25760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610338565b6001600160a01b0382166106345760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610338565b6001600160a01b038316600090815260208190526040902054818110156106ac5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610338565b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906106e39084906108d1565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161072f91815260200190565b60405180910390a350505050565b600060208083528351808285015260005b8181101561076a5785810183015185820160400152820161074e565b8181111561077c576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146107a957600080fd5b919050565b600080604083850312156107c157600080fd5b6107ca83610792565b946020939093013593505050565b6000806000606084860312156107ed57600080fd5b6107f684610792565b925061080460208501610792565b9150604084013590509250925092565b60006020828403121561082657600080fd5b61082f82610792565b9392505050565b6000806040838503121561084957600080fd5b61085283610792565b915061086060208401610792565b90509250929050565b600181811c9082168061087d57607f821691505b6020821081141561089e57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000828210156108cc576108cc6108a4565b500390565b600082198211156108e4576108e46108a4565b50019056fea264697066735822122030a282fb7e0b734096beb9323062edce33d11c6ccd7166512f1150282b9d8c8a64736f6c634300080a0033a2646970667358221220a343e67087c843940f5d01cf08cc6bb77beecfc24ee508b7d14cc759a0d3b10564736f6c634300080a0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

677261766974792d6272696467652d6d61696e6e65740000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000cc00000000000000000000000000000000000000000000000000000000000000062000000000000000000000000d02ec8a3fa36cad9d0e6c57b2b8dac9c919bf47e000000000000000000000000d06615eb94920948fededf59e012f688274db5270000000000000000000000001346d2b524c7f8d5549d5f3e87cce3904aa9b4cb000000000000000000000000bdadee22baf8ea072351ef197f48a76c3c18261a000000000000000000000000f6558340163774cc70b38bc1480e21065b0adde80000000000000000000000002c9df7dbe6e73f0b2a1045d1ae608a5230915fee000000000000000000000000042d9cdd6548b51456115000a777f3c59569d99700000000000000000000000011ea1cf1dd5fd9315d45cb6c15e901cb5159d8bb000000000000000000000000fd272eab659160c9ed5a89296a0ca21d28766b6d000000000000000000000000def65f9f0caef14616e2f2ed1945b68ad66562750000000000000000000000003e8ebde4324526ed7119ebc557886b84f9e92c0a0000000000000000000000006299a50d80549dfc758b335e174a2bfac81d6c62000000000000000000000000ac6d6d4ecdeb8d1174e1d948f71f0ba0c331ff920000000000000000000000008f7d963b5402bf073a67ba800b98d788213367c4000000000000000000000000a7298bc2025623626fe139ac65443112a9964953000000000000000000000000659b31cf9b3eff48aaa2f69a29cd96b331a5dde2000000000000000000000000e7b73fa6b0965faf3ec97efa884e7dd6d741e8bb0000000000000000000000002e5c835adb3f9561ded370bd8ad06a8306254f03000000000000000000000000026504d0c32a99205de5af38875864ede58a746f000000000000000000000000af15575b8cfee665a215606a76313fce2eeb5aa90000000000000000000000007beb98a706033fa28b22098a160974c270325da2000000000000000000000000f08506576345fb6abb6a80fcec2d34e4c547c8060000000000000000000000000c84b0299018757c8a94cad699800b68856acbab00000000000000000000000006a49340adeabbbea0b850c581cd07c5a1e57c47000000000000000000000000eb529af497f6736ed9eeb2749edc6c38658f32cf0000000000000000000000006259523bc13e1e3ec964d3cdf9da9517958804cb000000000000000000000000c16e3b44b0779d4b183a581055c7fef55ed25519000000000000000000000000048de1810eee92d2c540125c9a4896ea5c064c67000000000000000000000000049796a46ad4e24e6feea4f836b56c407484b52c000000000000000000000000097ee4acab904d9b477e4fc49c7e1ea67b460bc90000000000000000000000001864f0c868eedcc541391dbcf95028bed3dfbe590000000000000000000000001a055371f135c350df98d43be53a71d719f987d90000000000000000000000001d039a919efb8d88e5c24d8011c1581beaa4e8c30000000000000000000000001bcc53de17f04151865912e29173105653727cff00000000000000000000000020f604dc5a3d49b93b21bd40227f43dc37b3106e00000000000000000000000021872c12b1bab85607399b2ee36be75116d708a400000000000000000000000023f91f6a4d0d33d0a48c0728b5f4fb51d4c85edb000000000000000000000000290515f2a26f70c34daf51448c983d3931ea352b0000000000000000000000002982ceaba98bab8ec05a067ffe3a1c2ec3c610c30000000000000000000000002e28d0fc5fd9a0eb807f9c3ea1a0aa43ad7da86c0000000000000000000000002ba80daad13b74ff72dab650fc55a8df343190f20000000000000000000000002c0c794c54a2f6fb37a636da651f00c19497d6ce00000000000000000000000031c32051fca40b133cf9970cfaf141c11ec32512000000000000000000000000366fb970995e737a7b6eb8be8c46b0a5f6392aa100000000000000000000000038a838a8783d5f47b09d28c5c5107e72b880669e0000000000000000000000003d38ca4e28d3e60c16aeaf5617a32a0682211a940000000000000000000000004902d2683cc0123c1fea82ebc361a8f58fb8305500000000000000000000000052173e859a91551a383b3bc96d40d73114ff038700000000000000000000000052511a2b60cfd6e1fb0af37b7ba0a1d8ef82b0ca00000000000000000000000053093609e41632ade1108d22c98e7a90c9e51101000000000000000000000000532a1deebc5c54ec93627866cfc9007be2f6181300000000000000000000000054848e2870925d2a0df158feb10a9f99c45f8f3d000000000000000000000000577de4619f91d8fd5e434af791318a45db166d370000000000000000000000005b390b4256279dbdd9b699853edd787a97975a4d0000000000000000000000005c1522670a750d548ce767eba332d09e171a196d0000000000000000000000005deb18a724df51902e0742d7477340ab80fe611c000000000000000000000000624977fe6a9f887fa858957b3b92b39423b43b3200000000000000000000000063e37e48f29f1b2aca247e045d6244309cba577e000000000000000000000000646f836b0a88a7a1dc2dfddee260b4c86a583fa40000000000000000000000006b1dfe7ca2e93b6a0b534d140b02054deaa834490000000000000000000000007960c3c30718f9f99137956646763146736802340000000000000000000000007baa546a8af98076e0ff868730f1c30a50a0a7f20000000000000000000000007e33410db54e9eadf619911b2e4d404fa08a7f3d0000000000000000000000007f96379a0f136176270f382b37c6215b2f25790300000000000000000000000082a2ef1df41bdec4292ddbf8fca870ca40a253cd00000000000000000000000082b72ce9b848b91d3943867eca064bc4b3504a8f00000000000000000000000083377eb59ffbf333179d241457e4efdbdb9f7bc10000000000000000000000008477bf7c6d465405a840570a405a2973d9dc8d520000000000000000000000008f8011fda21d25d9c4846790d6ef66c8398cc3b50000000000000000000000008be231e6ed8e002cac60ca2284e6ef377c188eca0000000000000000000000009384803b6a8f07b13691e40747933c09b6c5635600000000000000000000000098f99515c0a44eb4f45f33bd41eea304da13e4000000000000000000000000009f7bbb1f313e8bc7309ab6be429ebf1df0fd54fe000000000000000000000000a17e673d399308aa4f6f80065e484058b1bc69c3000000000000000000000000be365629ced317dd785328a0c4425dd1be1c6f8c000000000000000000000000caa8b3e3bf2385c74041a96b6599560e68808a46000000000000000000000000dca8c176c2610adc07e84b008cc5b6dbbcce7236000000000000000000000000db6b96055156908d1263796ce559cccacdef3d7b000000000000000000000000de328ee7b3a6e3918a54ea8765d09e841ad5f56a000000000000000000000000e20d2fda099815b5b7724712d39b97daacb4b855000000000000000000000000a61889a82f66a9286075e2bf3984e49df28a9a11000000000000000000000000b1d6785e38ba13a35e479222dab48e083b18a282000000000000000000000000b3261b22e3fd1715ec639b1a8f1edea8ed3163dd000000000000000000000000b9d03c913e368a0137b2d08d75263525ad3fccfc000000000000000000000000bc3f6a075c931ce5d9d6a20d8ee652d940cf5b7a000000000000000000000000c0043256d85d56194fe50e83bc819c4dcb1d9a97000000000000000000000000c20f0557cf68ed2ea1227473960fcb532a0f430b000000000000000000000000c6de773e6f30155f55468e0b3ddb612904225597000000000000000000000000cebfd2dd7b42032582fccd2b6a9bba88a2e4ebf0000000000000000000000000d059ee08dacf95c91940515aec6353bdcd587929000000000000000000000000d5bc4fea09f514a1c86ba06dad51aeb8edefdd34000000000000000000000000d9bc82708848dca0eccb6d51712185da2a8cadee000000000000000000000000e0fbe446c1fb21f42aa41f9edcf8a6611c86d419000000000000000000000000ef2403fe087a250697d9d93709466bf51d228188000000000000000000000000eb60b3c0ed0c75a4ed52d27a7f505e596afa9e3e000000000000000000000000ee320c1e727bc617545a8ae09e71b85dbef7a8e4000000000000000000000000f65615165d3520a4b804a7710f17a687a2164c79000000000000000000000000fa42a24df34df089413e9aceb162b7c8f02131f90000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000002344dc27000000000000000000000000000000000000000000000000000000000246b8a9000000000000000000000000000000000000000000000000000000000246b561000000000000000000000000000000000000000000000000000000000246b48f000000000000000000000000000000000000000000000000000000000246b48f000000000000000000000000000000000000000000000000000000000246b3bd000000000000000000000000000000000000000000000000000000000246b2eb000000000000000000000000000000000000000000000000000000000246b2eb000000000000000000000000000000000000000000000000000000000246b2eb000000000000000000000000000000000000000000000000000000000246b147000000000000000000000000000000000000000000000000000000000246b075000000000000000000000000000000000000000000000000000000000246b075000000000000000000000000000000000000000000000000000000000246b075000000000000000000000000000000000000000000000000000000000246aed1000000000000000000000000000000000000000000000000000000000246ad2d000000000000000000000000000000000000000000000000000000000246ac5b000000000000000000000000000000000000000000000000000000000246a9e6000000000000000000000000000000000000000000000000000000000246a914000000000000000000000000000000000000000000000000000000000246a428000000000000000000000000000000000000000000000000000000000246a0e0000000000000000000000000000000000000000000000000000000000246a00e0000000000000000000000000000000000000000000000000000000002469e6a0000000000000000000000000000000000000000000000000000000002469b220000000000000000000000000000000000000000000000000000000002469636000000000000000000000000000000000000000000000000000000000246949300000000000000000000000000000000000000000000000000000000024693c10000000000000000000000000000000000000000000000000000000002468b8d00000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b500000000000000000000000000000000000000000000000000000000024681b5

-----Decoded View---------------
Arg [0] : _gravityId (bytes32): 0x677261766974792d6272696467652d6d61696e6e657400000000000000000000
Arg [1] : _validators (address[]): 0xD02Ec8a3FA36cAD9D0E6C57b2b8Dac9C919bf47e,0xD06615eB94920948fEDedF59E012F688274dB527,0x1346D2B524C7f8D5549d5F3e87cCe3904Aa9b4Cb,0xbdAdeE22bAf8Ea072351Ef197F48a76C3c18261A,0xf6558340163774Cc70b38bC1480e21065B0adDE8,0x2C9df7dBE6E73f0B2a1045D1aE608A5230915FEe,0x042d9CDD6548b51456115000A777f3C59569D997,0x11Ea1Cf1DD5Fd9315d45Cb6C15e901CB5159d8bB,0xFD272eaB659160c9Ed5a89296A0cA21D28766b6D,0xdEf65f9f0caEF14616e2F2ED1945B68aD6656275,0x3E8EbDE4324526ED7119EBC557886b84F9e92C0A,0x6299A50D80549Dfc758b335E174a2bfac81D6c62,0xaC6d6d4eCDEb8d1174e1D948F71f0BA0c331fF92,0x8F7d963b5402Bf073A67bA800B98d788213367c4,0xA7298bc2025623626fE139aC65443112A9964953,0x659B31CF9B3efF48AAA2F69A29Cd96B331a5dDe2,0xE7B73fA6B0965FaF3eC97eFa884E7Dd6d741e8bB,0x2e5c835ADb3f9561DEd370Bd8Ad06a8306254f03,0x026504d0c32A99205de5af38875864EDe58a746F,0xAF15575b8CFEe665a215606A76313Fce2EEb5Aa9,0x7bEb98A706033FA28b22098a160974C270325dA2,0xF08506576345fB6abB6A80fCec2d34E4c547C806,0x0c84B0299018757c8a94CAD699800B68856aCbAB,0x06a49340ADEabbBeA0B850C581cd07C5A1E57C47,0xEB529af497f6736Ed9EEb2749EDC6C38658F32cF,0x6259523bc13e1e3ec964d3cdF9Da9517958804cb,0xC16E3B44b0779D4b183A581055c7fef55ed25519,0x048de1810EEE92D2c540125c9A4896ea5C064C67,0x049796a46Ad4E24E6Feea4f836B56c407484B52c,0x097Ee4aCaB904d9b477e4fc49c7E1EA67B460Bc9,0x1864F0C868EeDcC541391DBcf95028beD3DFbE59,0x1A055371f135c350dF98d43be53A71d719F987D9,0x1D039a919efB8D88e5c24d8011c1581BEaa4e8c3,0x1bCc53de17F04151865912e29173105653727CfF,0x20f604dC5A3d49b93B21bD40227f43Dc37B3106E,0x21872c12b1BAb85607399b2EE36be75116D708a4,0x23F91f6a4D0D33d0A48C0728B5F4Fb51D4C85Edb,0x290515f2A26f70C34DAF51448C983d3931EA352B,0x2982CEAbA98Bab8ec05A067fFe3a1c2EC3C610C3,0x2E28d0FC5FD9A0EB807f9c3ea1a0aA43ad7DA86C,0x2bA80daaD13B74ff72Dab650fc55A8Df343190F2,0x2c0C794c54a2F6fb37A636DA651f00C19497D6Ce,0x31C32051Fca40b133cf9970CFAf141C11ec32512,0x366fb970995E737A7b6eb8be8c46b0a5f6392aA1,0x38a838A8783D5F47B09D28c5C5107E72B880669E,0x3D38Ca4E28d3E60c16aeAf5617A32A0682211A94,0x4902D2683Cc0123C1fEa82eBc361A8F58FB83055,0x52173E859a91551A383b3bC96D40D73114FF0387,0x52511A2B60CFD6E1fb0AF37B7ba0a1D8Ef82B0CA,0x53093609E41632aDE1108D22C98e7a90C9E51101,0x532A1DEEBc5C54Ec93627866CfC9007Be2F61813,0x54848E2870925D2A0DF158fEB10A9F99c45F8F3D,0x577dE4619f91D8fD5e434af791318a45dB166d37,0x5B390B4256279DBdd9B699853eDD787A97975a4d,0x5C1522670a750D548CE767EbA332d09E171A196d,0x5deb18a724df51902E0742D7477340aB80fe611C,0x624977fe6A9F887fA858957b3B92B39423b43B32,0x63E37E48f29f1b2Aca247e045d6244309CBA577E,0x646F836b0a88A7a1dc2DfddeE260b4C86A583fA4,0x6b1dFe7Ca2e93B6A0b534d140B02054deAa83449,0x7960c3C30718F9f9913795664676314673680234,0x7BAa546A8Af98076E0Ff868730f1C30a50a0a7f2,0x7e33410Db54e9Eadf619911b2E4D404fA08a7F3d,0x7f96379a0F136176270F382B37c6215B2f257903,0x82A2EF1df41bDEc4292DDbF8fca870ca40a253Cd,0x82B72Ce9b848B91D3943867eCA064Bc4B3504A8f,0x83377EB59FfBF333179D241457E4efDbDb9f7bc1,0x8477Bf7C6D465405A840570A405A2973D9dC8d52,0x8F8011FdA21d25D9c4846790D6EF66C8398cc3B5,0x8be231e6eD8E002cAC60Ca2284e6ef377c188eCA,0x9384803B6a8F07B13691e40747933C09B6c56356,0x98f99515C0a44EB4f45f33bD41eea304Da13e400,0x9F7BBb1F313E8bC7309aB6bE429Ebf1dF0FD54fE,0xA17e673D399308AA4f6F80065E484058B1bc69c3,0xBe365629Ced317dd785328A0C4425dd1be1c6F8C,0xCaa8B3e3Bf2385c74041a96b6599560E68808a46,0xDCa8C176C2610aDc07e84B008CC5b6DBbCCe7236,0xDb6b96055156908d1263796ce559cCCacdEf3D7B,0xDe328ee7B3A6e3918A54eA8765D09E841aD5F56A,0xE20d2Fda099815b5b7724712D39b97DaAcb4b855,0xa61889A82f66A9286075e2Bf3984e49Df28a9a11,0xb1D6785e38BA13a35E479222DAB48e083b18A282,0xb3261B22e3FD1715EC639b1A8f1EDea8ed3163DD,0xb9D03c913e368a0137B2D08D75263525aD3fCCfC,0xbC3f6a075C931cE5D9D6a20D8eE652D940cF5b7A,0xc0043256d85d56194FE50E83Bc819c4dcB1D9a97,0xc20f0557cf68ED2Ea1227473960Fcb532A0f430b,0xc6dE773E6f30155f55468E0B3DDb612904225597,0xceBFD2DD7B42032582fccD2B6A9bBa88a2e4EbF0,0xd059Ee08dAcF95c91940515Aec6353Bdcd587929,0xd5bC4fEa09F514a1c86Ba06DAd51aEb8eDefdd34,0xd9BC82708848DcA0eCCb6d51712185Da2A8cADeE,0xe0fBe446c1FB21F42Aa41F9edCf8a6611c86D419,0xeF2403Fe087A250697D9D93709466bf51d228188,0xeb60b3c0ed0c75a4eD52D27A7f505E596Afa9E3E,0xee320c1e727bc617545A8ae09e71B85DBef7A8e4,0xf65615165D3520a4b804A7710F17a687A2164C79,0xfa42A24Df34df089413E9aceB162B7c8F02131f9
Arg [2] : _powers (uint256[]): 591715367,38189225,38188385,38188175,38188175,38187965,38187755,38187755,38187755,38187335,38187125,38187125,38187125,38186705,38186285,38186075,38185446,38185236,38183976,38183136,38182926,38182506,38181666,38180406,38179987,38179777,38177677,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157,38175157

-----Encoded View---------------
201 Constructor Arguments found :
Arg [0] : 677261766974792d6272696467652d6d61696e6e657400000000000000000000
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000cc0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000062
Arg [4] : 000000000000000000000000d02ec8a3fa36cad9d0e6c57b2b8dac9c919bf47e
Arg [5] : 000000000000000000000000d06615eb94920948fededf59e012f688274db527
Arg [6] : 0000000000000000000000001346d2b524c7f8d5549d5f3e87cce3904aa9b4cb
Arg [7] : 000000000000000000000000bdadee22baf8ea072351ef197f48a76c3c18261a
Arg [8] : 000000000000000000000000f6558340163774cc70b38bc1480e21065b0adde8
Arg [9] : 0000000000000000000000002c9df7dbe6e73f0b2a1045d1ae608a5230915fee
Arg [10] : 000000000000000000000000042d9cdd6548b51456115000a777f3c59569d997
Arg [11] : 00000000000000000000000011ea1cf1dd5fd9315d45cb6c15e901cb5159d8bb
Arg [12] : 000000000000000000000000fd272eab659160c9ed5a89296a0ca21d28766b6d
Arg [13] : 000000000000000000000000def65f9f0caef14616e2f2ed1945b68ad6656275
Arg [14] : 0000000000000000000000003e8ebde4324526ed7119ebc557886b84f9e92c0a
Arg [15] : 0000000000000000000000006299a50d80549dfc758b335e174a2bfac81d6c62
Arg [16] : 000000000000000000000000ac6d6d4ecdeb8d1174e1d948f71f0ba0c331ff92
Arg [17] : 0000000000000000000000008f7d963b5402bf073a67ba800b98d788213367c4
Arg [18] : 000000000000000000000000a7298bc2025623626fe139ac65443112a9964953
Arg [19] : 000000000000000000000000659b31cf9b3eff48aaa2f69a29cd96b331a5dde2
Arg [20] : 000000000000000000000000e7b73fa6b0965faf3ec97efa884e7dd6d741e8bb
Arg [21] : 0000000000000000000000002e5c835adb3f9561ded370bd8ad06a8306254f03
Arg [22] : 000000000000000000000000026504d0c32a99205de5af38875864ede58a746f
Arg [23] : 000000000000000000000000af15575b8cfee665a215606a76313fce2eeb5aa9
Arg [24] : 0000000000000000000000007beb98a706033fa28b22098a160974c270325da2
Arg [25] : 000000000000000000000000f08506576345fb6abb6a80fcec2d34e4c547c806
Arg [26] : 0000000000000000000000000c84b0299018757c8a94cad699800b68856acbab
Arg [27] : 00000000000000000000000006a49340adeabbbea0b850c581cd07c5a1e57c47
Arg [28] : 000000000000000000000000eb529af497f6736ed9eeb2749edc6c38658f32cf
Arg [29] : 0000000000000000000000006259523bc13e1e3ec964d3cdf9da9517958804cb
Arg [30] : 000000000000000000000000c16e3b44b0779d4b183a581055c7fef55ed25519
Arg [31] : 000000000000000000000000048de1810eee92d2c540125c9a4896ea5c064c67
Arg [32] : 000000000000000000000000049796a46ad4e24e6feea4f836b56c407484b52c
Arg [33] : 000000000000000000000000097ee4acab904d9b477e4fc49c7e1ea67b460bc9
Arg [34] : 0000000000000000000000001864f0c868eedcc541391dbcf95028bed3dfbe59
Arg [35] : 0000000000000000000000001a055371f135c350df98d43be53a71d719f987d9
Arg [36] : 0000000000000000000000001d039a919efb8d88e5c24d8011c1581beaa4e8c3
Arg [37] : 0000000000000000000000001bcc53de17f04151865912e29173105653727cff
Arg [38] : 00000000000000000000000020f604dc5a3d49b93b21bd40227f43dc37b3106e
Arg [39] : 00000000000000000000000021872c12b1bab85607399b2ee36be75116d708a4
Arg [40] : 00000000000000000000000023f91f6a4d0d33d0a48c0728b5f4fb51d4c85edb
Arg [41] : 000000000000000000000000290515f2a26f70c34daf51448c983d3931ea352b
Arg [42] : 0000000000000000000000002982ceaba98bab8ec05a067ffe3a1c2ec3c610c3
Arg [43] : 0000000000000000000000002e28d0fc5fd9a0eb807f9c3ea1a0aa43ad7da86c
Arg [44] : 0000000000000000000000002ba80daad13b74ff72dab650fc55a8df343190f2
Arg [45] : 0000000000000000000000002c0c794c54a2f6fb37a636da651f00c19497d6ce
Arg [46] : 00000000000000000000000031c32051fca40b133cf9970cfaf141c11ec32512
Arg [47] : 000000000000000000000000366fb970995e737a7b6eb8be8c46b0a5f6392aa1
Arg [48] : 00000000000000000000000038a838a8783d5f47b09d28c5c5107e72b880669e
Arg [49] : 0000000000000000000000003d38ca4e28d3e60c16aeaf5617a32a0682211a94
Arg [50] : 0000000000000000000000004902d2683cc0123c1fea82ebc361a8f58fb83055
Arg [51] : 00000000000000000000000052173e859a91551a383b3bc96d40d73114ff0387
Arg [52] : 00000000000000000000000052511a2b60cfd6e1fb0af37b7ba0a1d8ef82b0ca
Arg [53] : 00000000000000000000000053093609e41632ade1108d22c98e7a90c9e51101
Arg [54] : 000000000000000000000000532a1deebc5c54ec93627866cfc9007be2f61813
Arg [55] : 00000000000000000000000054848e2870925d2a0df158feb10a9f99c45f8f3d
Arg [56] : 000000000000000000000000577de4619f91d8fd5e434af791318a45db166d37
Arg [57] : 0000000000000000000000005b390b4256279dbdd9b699853edd787a97975a4d
Arg [58] : 0000000000000000000000005c1522670a750d548ce767eba332d09e171a196d
Arg [59] : 0000000000000000000000005deb18a724df51902e0742d7477340ab80fe611c
Arg [60] : 000000000000000000000000624977fe6a9f887fa858957b3b92b39423b43b32
Arg [61] : 00000000000000000000000063e37e48f29f1b2aca247e045d6244309cba577e
Arg [62] : 000000000000000000000000646f836b0a88a7a1dc2dfddee260b4c86a583fa4
Arg [63] : 0000000000000000000000006b1dfe7ca2e93b6a0b534d140b02054deaa83449
Arg [64] : 0000000000000000000000007960c3c30718f9f9913795664676314673680234
Arg [65] : 0000000000000000000000007baa546a8af98076e0ff868730f1c30a50a0a7f2
Arg [66] : 0000000000000000000000007e33410db54e9eadf619911b2e4d404fa08a7f3d
Arg [67] : 0000000000000000000000007f96379a0f136176270f382b37c6215b2f257903
Arg [68] : 00000000000000000000000082a2ef1df41bdec4292ddbf8fca870ca40a253cd
Arg [69] : 00000000000000000000000082b72ce9b848b91d3943867eca064bc4b3504a8f
Arg [70] : 00000000000000000000000083377eb59ffbf333179d241457e4efdbdb9f7bc1
Arg [71] : 0000000000000000000000008477bf7c6d465405a840570a405a2973d9dc8d52
Arg [72] : 0000000000000000000000008f8011fda21d25d9c4846790d6ef66c8398cc3b5
Arg [73] : 0000000000000000000000008be231e6ed8e002cac60ca2284e6ef377c188eca
Arg [74] : 0000000000000000000000009384803b6a8f07b13691e40747933c09b6c56356
Arg [75] : 00000000000000000000000098f99515c0a44eb4f45f33bd41eea304da13e400
Arg [76] : 0000000000000000000000009f7bbb1f313e8bc7309ab6be429ebf1df0fd54fe
Arg [77] : 000000000000000000000000a17e673d399308aa4f6f80065e484058b1bc69c3
Arg [78] : 000000000000000000000000be365629ced317dd785328a0c4425dd1be1c6f8c
Arg [79] : 000000000000000000000000caa8b3e3bf2385c74041a96b6599560e68808a46
Arg [80] : 000000000000000000000000dca8c176c2610adc07e84b008cc5b6dbbcce7236
Arg [81] : 000000000000000000000000db6b96055156908d1263796ce559cccacdef3d7b
Arg [82] : 000000000000000000000000de328ee7b3a6e3918a54ea8765d09e841ad5f56a
Arg [83] : 000000000000000000000000e20d2fda099815b5b7724712d39b97daacb4b855
Arg [84] : 000000000000000000000000a61889a82f66a9286075e2bf3984e49df28a9a11
Arg [85] : 000000000000000000000000b1d6785e38ba13a35e479222dab48e083b18a282
Arg [86] : 000000000000000000000000b3261b22e3fd1715ec639b1a8f1edea8ed3163dd
Arg [87] : 000000000000000000000000b9d03c913e368a0137b2d08d75263525ad3fccfc
Arg [88] : 000000000000000000000000bc3f6a075c931ce5d9d6a20d8ee652d940cf5b7a
Arg [89] : 000000000000000000000000c0043256d85d56194fe50e83bc819c4dcb1d9a97
Arg [90] : 000000000000000000000000c20f0557cf68ed2ea1227473960fcb532a0f430b
Arg [91] : 000000000000000000000000c6de773e6f30155f55468e0b3ddb612904225597
Arg [92] : 000000000000000000000000cebfd2dd7b42032582fccd2b6a9bba88a2e4ebf0
Arg [93] : 000000000000000000000000d059ee08dacf95c91940515aec6353bdcd587929
Arg [94] : 000000000000000000000000d5bc4fea09f514a1c86ba06dad51aeb8edefdd34
Arg [95] : 000000000000000000000000d9bc82708848dca0eccb6d51712185da2a8cadee
Arg [96] : 000000000000000000000000e0fbe446c1fb21f42aa41f9edcf8a6611c86d419
Arg [97] : 000000000000000000000000ef2403fe087a250697d9d93709466bf51d228188
Arg [98] : 000000000000000000000000eb60b3c0ed0c75a4ed52d27a7f505e596afa9e3e
Arg [99] : 000000000000000000000000ee320c1e727bc617545a8ae09e71b85dbef7a8e4
Arg [100] : 000000000000000000000000f65615165d3520a4b804a7710f17a687a2164c79
Arg [101] : 000000000000000000000000fa42a24df34df089413e9aceb162b7c8f02131f9
Arg [102] : 0000000000000000000000000000000000000000000000000000000000000062
Arg [103] : 000000000000000000000000000000000000000000000000000000002344dc27
Arg [104] : 000000000000000000000000000000000000000000000000000000000246b8a9
Arg [105] : 000000000000000000000000000000000000000000000000000000000246b561
Arg [106] : 000000000000000000000000000000000000000000000000000000000246b48f
Arg [107] : 000000000000000000000000000000000000000000000000000000000246b48f
Arg [108] : 000000000000000000000000000000000000000000000000000000000246b3bd
Arg [109] : 000000000000000000000000000000000000000000000000000000000246b2eb
Arg [110] : 000000000000000000000000000000000000000000000000000000000246b2eb
Arg [111] : 000000000000000000000000000000000000000000000000000000000246b2eb
Arg [112] : 000000000000000000000000000000000000000000000000000000000246b147
Arg [113] : 000000000000000000000000000000000000000000000000000000000246b075
Arg [114] : 000000000000000000000000000000000000000000000000000000000246b075
Arg [115] : 000000000000000000000000000000000000000000000000000000000246b075
Arg [116] : 000000000000000000000000000000000000000000000000000000000246aed1
Arg [117] : 000000000000000000000000000000000000000000000000000000000246ad2d
Arg [118] : 000000000000000000000000000000000000000000000000000000000246ac5b
Arg [119] : 000000000000000000000000000000000000000000000000000000000246a9e6
Arg [120] : 000000000000000000000000000000000000000000000000000000000246a914
Arg [121] : 000000000000000000000000000000000000000000000000000000000246a428
Arg [122] : 000000000000000000000000000000000000000000000000000000000246a0e0
Arg [123] : 000000000000000000000000000000000000000000000000000000000246a00e
Arg [124] : 0000000000000000000000000000000000000000000000000000000002469e6a
Arg [125] : 0000000000000000000000000000000000000000000000000000000002469b22
Arg [126] : 0000000000000000000000000000000000000000000000000000000002469636
Arg [127] : 0000000000000000000000000000000000000000000000000000000002469493
Arg [128] : 00000000000000000000000000000000000000000000000000000000024693c1
Arg [129] : 0000000000000000000000000000000000000000000000000000000002468b8d
Arg [130] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [131] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [132] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [133] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [134] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [135] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [136] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [137] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [138] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [139] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [140] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [141] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [142] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [143] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [144] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [145] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [146] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [147] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [148] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [149] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [150] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [151] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [152] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [153] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [154] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [155] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [156] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [157] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [158] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [159] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [160] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [161] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [162] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [163] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [164] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [165] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [166] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [167] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [168] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [169] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [170] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [171] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [172] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [173] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [174] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [175] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [176] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [177] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [178] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [179] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [180] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [181] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [182] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [183] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [184] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [185] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [186] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [187] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [188] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [189] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [190] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [191] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [192] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [193] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [194] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [195] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [196] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [197] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [198] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [199] : 00000000000000000000000000000000000000000000000000000000024681b5
Arg [200] : 00000000000000000000000000000000000000000000000000000000024681b5


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

OVERVIEW

An open, decentralized bridge that unlocks the power of interoperability & liquidity between the Ethereum and Cosmos ecosystems.

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Chain Token Portfolio % Price Amount Value
ETH64.20%$16,973,468.9091$6,973,468.91
ETH14.72%$3,361.27475.5556$1,598,468.57
ETH9.27%$0.05043119,966,349.7965$1,006,922.99
ETH5.34%$1578,935.8232$579,514.76
ETH4.42%$2,732.78175.6194$479,929.26
ETH0.85%$528.56174.5291$92,249.1
ETH0.74%$0.00230434,895,483.8949$80,401.99
ETH0.14%$98,1940.1508$14,807.88
ETH0.08%$7.911,034.5086$8,180.21
ETH0.05%$3,973.511.4336$5,696.43
ETH0.04%$14,695.7338$4,695.73
ETH0.04%$0.000027141,047,347.7684$3,836.49
ETH0.03%$257.4510.7713$2,773.08
ETH0.02%$0.0019111,314,816.6888$2,513.1
ETH0.02%$28.8768.1887$1,968.62
ETH0.01%$1.411,147.6034$1,618.12
ETH<0.01%$0.009896105,159.5141$1,040.66
ETH<0.01%$0.03200627,833.4287$890.82
ETH<0.01%$0.02218522,661.5921$502.75
ETH<0.01%$0.831558581$483.14
ETH<0.01%$1.34242.9906$325.61
ETH<0.01%$0.499502476$237.76
ETH<0.01%$0.02468,929.0664$219.66
ETH<0.01%$0.00317952,281.5931$166.2
ETH<0.01%$1.12112.8572$126.4
ETH<0.01%$0.288959397.5999$114.89
ETH<0.01%$0.0000412,522,820.2701$102.17
ETH<0.01%$0.998309100$99.83
ETH<0.01%$454.310.2171$98.62
ETH<0.01%$0.0154266,095.9028$94.03
ETH<0.01%$3,359.110.0258$86.61
ETH<0.01%$0.0245463,476.2495$85.33
ETH<0.01%$10.148.1532$82.67
ETH<0.01%$10.497.4703$78.36
ETH<0.01%$0.000117623,802.0156$73.1
ETH<0.01%$389.040.15$58.36
ETH<0.01%$0.542761105.3168$57.16
ETH<0.01%$0.77677471.7483$55.73
ETH<0.01%$0.99631452.8032$52.61
ETH<0.01%$0.190903271.5665$51.84
ETH<0.01%$0.0307931,000$30.79
ETH<0.01%$1.4115.6155$22.02
ETH<0.01%$0.025621690$17.68
ETH<0.01%$0.0133281,150$15.33
ETH<0.01%$0.150311100.0172$15.03
ETH<0.01%$0.031179478.1231$14.91
ETH<0.01%$1.2710$12.7
ETH<0.01%$3.943.0499$12.02
ETH<0.01%$0.26525843.4582$11.53
ETH<0.01%$0.99199511$10.91
ETH<0.01%$0.017816567.5629$10.11
ETH<0.01%$0.007435943.8059$7.02
ETH<0.01%<$0.000001982,713,748$5.5
ETH<0.01%$0.54040910$5.4
ETH<0.01%$0.7529957$5.27
ETH<0.01%$0.51092810$5.11
ETH<0.01%$0.020462238.7907$4.89
ETH<0.01%$0.9606155$4.8
ETH<0.01%$0.11897240$4.76
ETH<0.01%$0.000007632,780.6518$4.42
ETH<0.01%$0.4223710$4.22
ETH<0.01%$0.05773661$3.52
ETH<0.01%$0.00024112,417.9958$2.99
ETH<0.01%$0.0027541,030.3423$2.84
ETH<0.01%$0.00459333.3942$1.53
ETH<0.01%$0.00002260,179.367$1.29
ETH<0.01%$0.02540250.7718$1.29
ETH<0.01%$0.0010611,000$1.06
ETH<0.01%$0.004469100$0.4469
ETH<0.01%$17.040.0179$0.3055
ETH<0.01%<$0.00000122,688,298.1441$0.2206
ETH<0.01%$1.060.1$0.1058
GNO<0.01%$0.9998740.2296$0.22954
BASE<0.01%$0.000554200$0.1107
POL<0.01%$0.5533610.0001$0.000055
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.