Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
There are no matching entriesUpdate your filters to view other transactions | |||||||||
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Erc20Vault
Compiler Version
v0.5.11+commit.c082d0b4
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.5.11;
import "./Vault.sol";
import "./verifiers/IErc20DepositVerifier.sol";
import "../framework/PlasmaFramework.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
contract Erc20Vault is Vault {
using SafeERC20 for IERC20;
event Erc20Withdrawn(
address indexed receiver,
address indexed token,
uint256 amount
);
event DepositCreated(
address indexed depositor,
uint256 indexed blknum,
address indexed token,
uint256 amount
);
constructor(PlasmaFramework _framework) public Vault(_framework) {}
/**
* @notice Deposits approved amount of ERC20 token(s) into the contract
* Once the deposit is recognized, the owner (depositor) can transact on the OmiseGO Network
* The approve function of the ERC20 token contract must be called before calling this function
* for at least the amount that is deposited into the contract
* @param depositTx RLP-encoded transaction to act as the deposit
*/
function deposit(bytes calldata depositTx) external {
address depositVerifier = super.getEffectiveDepositVerifier();
require(depositVerifier != address(0), "Deposit verifier has not been set");
(address depositor, address token, uint256 amount) = IErc20DepositVerifier(depositVerifier)
.verify(depositTx, msg.sender, address(this));
IERC20(token).safeTransferFrom(depositor, address(this), amount);
uint256 blknum = super.submitDepositBlock(depositTx);
emit DepositCreated(msg.sender, blknum, token, amount);
}
/**
* @notice Withdraw ERC20 tokens that have successfully exited from the OmiseGO Network
* @param receiver Address of the recipient
* @param token Address of ERC20 token contract
* @param amount Amount to transfer
*/
function withdraw(address payable receiver, address token, uint256 amount) external onlyFromNonQuarantinedExitGame {
IERC20(token).safeTransfer(receiver, amount);
emit Erc20Withdrawn(receiver, token, amount);
}
}pragma solidity 0.5.11;
import "./models/BlockModel.sol";
import "./registries/VaultRegistry.sol";
import "../utils/OnlyFromAddress.sol";
/**
* @notice Controls the logic and functions for block submissions in PlasmaFramework
* @dev There are two types of blocks: child block and deposit block
* Each child block has an interval of 'childBlockInterval'
* The interval is preserved for deposits. Each deposit results in one deposit block.
* For instance, a child block would be in block 1000 and the next deposit would result in block 1001.
*
* Only the authority address can perform a block submission.
* Details on limitations for the authority address can be found here: https://github.com/omisego/elixir-omg#managing-the-operator-address
*/
contract BlockController is OnlyFromAddress, VaultRegistry {
address public authority;
uint256 public childBlockInterval;
uint256 public nextChildBlock;
uint256 public nextDeposit;
bool public isChildChainActivated;
mapping (uint256 => BlockModel.Block) public blocks; // block number => Block data
event BlockSubmitted(
uint256 blknum
);
event ChildChainActivated(
address authority
);
constructor(
uint256 _interval,
uint256 _minExitPeriod,
uint256 _initialImmuneVaults,
address _authority
)
public
VaultRegistry(_minExitPeriod, _initialImmuneVaults)
{
authority = _authority;
childBlockInterval = _interval;
nextChildBlock = childBlockInterval;
nextDeposit = 1;
isChildChainActivated = false;
}
/**
* @notice Activates the child chain so that child chain can start to submit child blocks to root chain
* @notice Can only be called once by the authority.
* @notice Sets isChildChainActivated to true and emits the ChildChainActivated event.
* @dev This is a preserved action for authority account to start its nonce with 1.
* Child chain rely ethereum nonce to protect re-org: https://git.io/JecDG
* see discussion: https://git.io/JenaT, https://git.io/JecDO
*/
function activateChildChain() external onlyFrom(authority) {
require(isChildChainActivated == false, "Child chain already activated");
isChildChainActivated = true;
emit ChildChainActivated(authority);
}
/**
* @notice Allows the authority to submit the Merkle root of a Plasma block
* @dev emit BlockSubmitted event
* @dev Block number jumps 'childBlockInterval' per submission
* @dev See discussion in https://github.com/omisego/plasma-contracts/issues/233
* @param _blockRoot Merkle root of the Plasma block
*/
function submitBlock(bytes32 _blockRoot) external onlyFrom(authority) {
require(isChildChainActivated == true, "Child chain has not been activated by authority address yet");
uint256 submittedBlockNumber = nextChildBlock;
blocks[submittedBlockNumber] = BlockModel.Block({
root: _blockRoot,
timestamp: block.timestamp
});
nextChildBlock += childBlockInterval;
nextDeposit = 1;
emit BlockSubmitted(submittedBlockNumber);
}
/**
* @notice Submits a block for deposit
* @dev Block number adds 1 per submission; it's possible to have at most 'childBlockInterval' deposit blocks between two child chain blocks
* @param _blockRoot Merkle root of the Plasma block
* @return The deposit block number
*/
function submitDepositBlock(bytes32 _blockRoot) public onlyFromNonQuarantinedVault returns (uint256) {
require(isChildChainActivated == true, "Child chain has not been activated by authority address yet");
require(nextDeposit < childBlockInterval, "Exceeded limit of deposits per child block interval");
uint256 blknum = nextDepositBlock();
blocks[blknum] = BlockModel.Block({
root : _blockRoot,
timestamp : block.timestamp
});
nextDeposit++;
return blknum;
}
function nextDepositBlock() public view returns (uint256) {
return nextChildBlock - childBlockInterval + nextDeposit;
}
function isDeposit(uint256 blockNum) public view returns (bool) {
require(blocks[blockNum].timestamp != 0, "Block does not exist");
return blockNum % childBlockInterval != 0;
}
}pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;
import "./interfaces/IExitProcessor.sol";
import "./registries/ExitGameRegistry.sol";
import "./utils/PriorityQueue.sol";
import "./utils/ExitPriority.sol";
import "../utils/PosLib.sol";
/**
* @notice Controls the logic and functions for ExitGame to interact with the PlasmaFramework
* Plasma M(ore)VP relies on exit priority to secure the user from invalid transactions
* The priority queue ensures the exit is processed with the exit priority
* For details, see the Plasma MVP spec: https://ethresear.ch/t/minimal-viable-plasma/426
*/
contract ExitGameController is ExitGameRegistry {
// exit hashed (priority, vault id, token) => IExitProcessor
mapping (bytes32 => IExitProcessor) public delegations;
// hashed (vault id, token) => PriorityQueue
mapping (bytes32 => PriorityQueue) public exitsQueues;
// outputId => exitId
mapping (bytes32 => uint160) public outputsFinalizations;
bool private mutex = false;
event ExitQueueAdded(
uint256 vaultId,
address token
);
event ProcessedExitsNum(
uint256 processedNum,
uint256 vaultId,
address token
);
event ExitQueued(
uint160 indexed exitId,
uint256 priority
);
constructor(uint256 _minExitPeriod, uint256 _initialImmuneExitGames)
public
ExitGameRegistry(_minExitPeriod, _initialImmuneExitGames)
{
}
/**
* @dev Prevents reentrant calls by using a mutex.
*/
modifier nonReentrant() {
require(!mutex, "Reentrant call");
mutex = true;
_;
assert(mutex);
mutex = false;
}
/**
* @notice Activates non reentrancy mode
* Guards against reentering into publicly accessible code that modifies state related to exits
* @dev Accessible only from non quarantined exit games, uses a mutex
*/
function activateNonReentrant() external onlyFromNonQuarantinedExitGame() {
require(!mutex, "Reentrant call");
mutex = true;
}
/**
* @notice Deactivates non reentrancy mode
* @dev Accessible only from non quarantined exit games, uses a mutex
*/
function deactivateNonReentrant() external onlyFromNonQuarantinedExitGame() {
assert(mutex);
mutex = false;
}
/**
* @notice Checks if the queue for a specified token was created
* @param vaultId ID of the vault that handles the token
* @param token Address of the token
* @return bool Defines whether the queue for a token was created
*/
function hasExitQueue(uint256 vaultId, address token) public view returns (bool) {
bytes32 key = exitQueueKey(vaultId, token);
return hasExitQueue(key);
}
/**
* @notice Adds queue to the Plasma framework
* @dev The queue is created as a new contract instance
* @param vaultId ID of the vault
* @param token Address of the token
*/
function addExitQueue(uint256 vaultId, address token) external {
require(vaultId != 0, "Vault ID must not be 0");
bytes32 key = exitQueueKey(vaultId, token);
require(!hasExitQueue(key), "Exit queue exists");
exitsQueues[key] = new PriorityQueue();
emit ExitQueueAdded(vaultId, token);
}
/**
* @notice Enqueue exits from exit game contracts is a function that places the exit into the
* priority queue to enforce the priority of exit during 'processExits'
* @dev emits ExitQueued event, which can be used to back trace the priority inside the queue
* @dev Caller of this function should add "pragma experimental ABIEncoderV2;" on top of file
* @dev Priority (exitableAt, txPos, exitId) must be unique per queue. Do not enqueue when the same priority is already in the queue.
* @param vaultId Vault ID of the vault that stores exiting funds
* @param token Token for the exit
* @param exitableAt The earliest time a specified exit can be processed
* @param txPos Transaction position for the exit priority. For SE it should be the exit tx, for IFE it should be the youngest input tx position.
* @param exitId ID used by the exit processor contract to determine how to process the exit
* @param exitProcessor The exit processor contract, called during "processExits"
* @return A unique priority number computed for the exit
*/
function enqueue(
uint256 vaultId,
address token,
uint64 exitableAt,
PosLib.Position calldata txPos,
uint160 exitId,
IExitProcessor exitProcessor
)
external
onlyFromNonQuarantinedExitGame
returns (uint256)
{
bytes32 key = exitQueueKey(vaultId, token);
require(hasExitQueue(key), "The queue for the (vaultId, token) pair is not yet added to the Plasma framework");
PriorityQueue queue = exitsQueues[key];
uint256 priority = ExitPriority.computePriority(exitableAt, txPos, exitId);
queue.insert(priority);
bytes32 delegationKey = getDelegationKey(priority, vaultId, token);
require(address(delegations[delegationKey]) == address(0), "The same priority is already enqueued");
delegations[delegationKey] = exitProcessor;
emit ExitQueued(exitId, priority);
return priority;
}
/**
* @notice Processes any exits that have completed the challenge period. Exits are processed according to the exit priority.
* @dev Emits ProcessedExitsNum event
* @param vaultId Vault ID of the vault that stores exiting funds
* @param token The token type to process
* @param topExitId Unique identifier for prioritizing the first exit to process. Set to zero to skip this check.
* @param maxExitsToProcess Maximum number of exits to process
* @return Total number of processed exits
*/
function processExits(uint256 vaultId, address token, uint160 topExitId, uint256 maxExitsToProcess) external nonReentrant {
bytes32 key = exitQueueKey(vaultId, token);
require(hasExitQueue(key), "The token is not yet added to the Plasma framework");
PriorityQueue queue = exitsQueues[key];
require(queue.currentSize() > 0, "Exit queue is empty");
uint256 uniquePriority = queue.getMin();
uint160 exitId = ExitPriority.parseExitId(uniquePriority);
require(topExitId == 0 || exitId == topExitId,
"Top exit ID of the queue is different to the one specified");
bytes32 delegationKey = getDelegationKey(uniquePriority, vaultId, token);
IExitProcessor processor = delegations[delegationKey];
uint256 processedNum = 0;
while (processedNum < maxExitsToProcess && ExitPriority.parseExitableAt(uniquePriority) < block.timestamp) {
delete delegations[delegationKey];
queue.delMin();
processedNum++;
processor.processExit(exitId, vaultId, token);
if (queue.currentSize() == 0) {
break;
}
uniquePriority = queue.getMin();
delegationKey = getDelegationKey(uniquePriority, vaultId, token);
exitId = ExitPriority.parseExitId(uniquePriority);
processor = delegations[delegationKey];
}
emit ProcessedExitsNum(processedNum, vaultId, token);
}
/**
* @notice Checks whether any of the output with the given outputIds is already spent
* @param _outputIds Output IDs to check
*/
function isAnyInputFinalizedByOtherExit(bytes32[] calldata _outputIds, uint160 exitId) external view returns (bool) {
for (uint i = 0; i < _outputIds.length; i++) {
uint160 finalizedExitId = outputsFinalizations[_outputIds[i]];
if (finalizedExitId != 0 && finalizedExitId != exitId) {
return true;
}
}
return false;
}
/**
* @notice Batch flags already spent outputs (only not already spent)
* @param outputIds Output IDs to flag
*/
function batchFlagOutputsFinalized(bytes32[] calldata outputIds, uint160 exitId) external onlyFromNonQuarantinedExitGame {
for (uint i = 0; i < outputIds.length; i++) {
require(outputIds[i] != bytes32(""), "Should not flag with empty outputId");
if (outputsFinalizations[outputIds[i]] == 0) {
outputsFinalizations[outputIds[i]] = exitId;
}
}
}
/**
* @notice Flags a single output as spent if it is not flagged already
* @param outputId The output ID to flag as spent
*/
function flagOutputFinalized(bytes32 outputId, uint160 exitId) external onlyFromNonQuarantinedExitGame {
require(outputId != bytes32(""), "Should not flag with empty outputId");
if (outputsFinalizations[outputId] == 0) {
outputsFinalizations[outputId] = exitId;
}
}
/**
* @notice Checks whether output with a given outputId is finalized
* @param outputId Output ID to check
*/
function isOutputFinalized(bytes32 outputId) external view returns (bool) {
return outputsFinalizations[outputId] != 0;
}
function getNextExit(uint256 vaultId, address token) external view returns (uint256) {
bytes32 key = exitQueueKey(vaultId, token);
return exitsQueues[key].getMin();
}
function exitQueueKey(uint256 vaultId, address token) private pure returns (bytes32) {
return keccak256(abi.encodePacked(vaultId, token));
}
function hasExitQueue(bytes32 queueKey) private view returns (bool) {
return address(exitsQueues[queueKey]) != address(0);
}
function getDelegationKey(uint256 priority, uint256 vaultId, address token) private pure returns (bytes32) {
return keccak256(abi.encodePacked(priority, vaultId, token));
}
}pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;
import "./BlockController.sol";
import "./ExitGameController.sol";
import "./registries/VaultRegistry.sol";
import "./registries/ExitGameRegistry.sol";
contract PlasmaFramework is VaultRegistry, ExitGameRegistry, ExitGameController, BlockController {
uint256 public constant CHILD_BLOCK_INTERVAL = 1000;
/**
* The minimum finalization period is the Plasma guarantee that all exits are safe provided the user takes action within the specified time period
* When the child chain is rogue, user should start their exit and challenge any invalid exit within this period
* An exit can be processed/finalized after minimum two finalization periods from its inclusion position, unless it is an exit for a deposit,
* which would use one finalization period, instead of two
*
* For the Abstract Layer Design, OmiseGO also uses some multitude of this period to update its framework
* See also ExitGameRegistry.sol, VaultRegistry.sol, and Vault.sol for more information on the update waiting time (the quarantined period)
*
* MVP: https://ethresear.ch/t/minimal-viable-plasma/426
* MoreVP: https://github.com/omisego/elixir-omg/blob/master/docs/morevp.md#timeline
* Special period for deposit: https://git.io/JecCV
*/
uint256 public minExitPeriod;
address private maintainer;
string public version;
constructor(
uint256 _minExitPeriod,
uint256 _initialImmuneVaults,
uint256 _initialImmuneExitGames,
address _authority,
address _maintainer
)
public
BlockController(CHILD_BLOCK_INTERVAL, _minExitPeriod, _initialImmuneVaults, _authority)
ExitGameController(_minExitPeriod, _initialImmuneExitGames)
{
minExitPeriod = _minExitPeriod;
maintainer = _maintainer;
}
function getMaintainer() public view returns (address) {
return maintainer;
}
/**
* @notice Gets the semantic version of the current deployed contracts
*/
function getVersion() external view returns (string memory) {
return version;
}
/**
* @notice Sets the semantic version of the current deployed contracts
* @param _version is semver string
*/
function setVersion(string memory _version) public onlyFrom(getMaintainer()) {
version = _version;
}
}pragma solidity 0.5.11;
/**
* @notice Protocols for the PlasmaFramework
*/
library Protocol {
uint8 constant internal MVP_VALUE = 1;
uint8 constant internal MORE_VP_VALUE = 2;
// solhint-disable-next-line func-name-mixedcase
function MVP() internal pure returns (uint8) {
return MVP_VALUE;
}
// solhint-disable-next-line func-name-mixedcase
function MORE_VP() internal pure returns (uint8) {
return MORE_VP_VALUE;
}
function isValidProtocol(uint8 protocol) internal pure returns (bool) {
return protocol == MVP_VALUE || protocol == MORE_VP_VALUE;
}
}pragma solidity 0.5.11;
/**
* @dev An interface that allows custom logic to process exits for different requirements.
* This interface is used to dispatch to each custom processor when 'processExits' is called on PlasmaFramework.
*/
interface IExitProcessor {
/**
* @dev Function interface for processing exits.
* @param exitId Unique ID for exit per tx type
* @param vaultId ID of the vault that funds the exit
* @param token Address of the token contract
*/
function processExit(uint160 exitId, uint256 vaultId, address token) external;
}pragma solidity 0.5.11;
library BlockModel {
/**
* @notice Block data structure that is stored in the contract
* @param root The Merkle root block hash of the Plasma blocks
* @param timestamp The timestamp, in seconds, when the block is saved
*/
struct Block {
bytes32 root;
uint256 timestamp;
}
}pragma solidity 0.5.11;
import "openzeppelin-solidity/contracts/utils/Address.sol";
import "../Protocol.sol";
import "../utils/Quarantine.sol";
import "../../utils/OnlyFromAddress.sol";
contract ExitGameRegistry is OnlyFromAddress {
using Quarantine for Quarantine.Data;
mapping(uint256 => address) private _exitGames; // txType => exit game contract address
mapping(address => uint256) private _exitGameToTxType; // exit game contract address => tx type
mapping(uint256 => uint8) private _protocols; // tx type => protocol (MVP/MORE_VP)
Quarantine.Data private _exitGameQuarantine;
event ExitGameRegistered(
uint256 txType,
address exitGameAddress,
uint8 protocol
);
/**
* @dev It takes at least 3 * minExitPeriod before each new exit game contract is able to start protecting existing transactions
* see: https://github.com/omisego/plasma-contracts/issues/172
* https://github.com/omisego/plasma-contracts/issues/197
*/
constructor (uint256 _minExitPeriod, uint256 _initialImmuneExitGames)
public
{
_exitGameQuarantine.quarantinePeriod = 4 * _minExitPeriod;
_exitGameQuarantine.immunitiesRemaining = _initialImmuneExitGames;
}
/**
* @notice A modifier to verify that the call is from a non-quarantined exit game
*/
modifier onlyFromNonQuarantinedExitGame() {
require(_exitGameToTxType[msg.sender] != 0, "The call is not from a registered exit game contract");
require(!_exitGameQuarantine.isQuarantined(msg.sender), "ExitGame is quarantined");
_;
}
/**
* @notice interface to get the 'maintainer' address.
* @dev see discussion here: https://git.io/Je8is
*/
function getMaintainer() public view returns (address);
/**
* @notice Checks whether the contract is safe to use and is not under quarantine
* @dev Exposes information about exit games quarantine
* @param _contract Address of the exit game contract
* @return boolean Whether the contract is safe to use and is not under quarantine
*/
function isExitGameSafeToUse(address _contract) public view returns (bool) {
return _exitGameToTxType[_contract] != 0 && !_exitGameQuarantine.isQuarantined(_contract);
}
/**
* @notice Registers an exit game within the PlasmaFramework. Only the maintainer can call the function.
* @dev Emits ExitGameRegistered event to notify clients
* @param _txType The tx type where the exit game wants to register
* @param _contract Address of the exit game contract
* @param _protocol The transaction protocol, either 1 for MVP or 2 for MoreVP
*/
function registerExitGame(uint256 _txType, address _contract, uint8 _protocol) public onlyFrom(getMaintainer()) {
require(_txType != 0, "Should not register with tx type 0");
require(Address.isContract(_contract), "Should not register with a non-contract address");
require(_exitGames[_txType] == address(0), "The tx type is already registered");
require(_exitGameToTxType[_contract] == 0, "The exit game contract is already registered");
require(Protocol.isValidProtocol(_protocol), "Invalid protocol value");
_exitGames[_txType] = _contract;
_exitGameToTxType[_contract] = _txType;
_protocols[_txType] = _protocol;
_exitGameQuarantine.quarantine(_contract);
emit ExitGameRegistered(_txType, _contract, _protocol);
}
/**
* @notice Public getter for retrieving protocol with tx type
*/
function protocols(uint256 _txType) public view returns (uint8) {
return _protocols[_txType];
}
/**
* @notice Public getter for retrieving exit game address with tx type
*/
function exitGames(uint256 _txType) public view returns (address) {
return _exitGames[_txType];
}
/**
* @notice Public getter for retrieving tx type with exit game address
*/
function exitGameToTxType(address _exitGame) public view returns (uint256) {
return _exitGameToTxType[_exitGame];
}
}pragma solidity 0.5.11;
import "openzeppelin-solidity/contracts/utils/Address.sol";
import "../utils/Quarantine.sol";
import "../../utils/OnlyFromAddress.sol";
contract VaultRegistry is OnlyFromAddress {
using Quarantine for Quarantine.Data;
mapping(uint256 => address) private _vaults; // vault id => vault address
mapping(address => uint256) private _vaultToId; // vault address => vault id
Quarantine.Data private _vaultQuarantine;
event VaultRegistered(
uint256 vaultId,
address vaultAddress
);
/**
* @dev It takes at least 2 minExitPeriod for each new vault contract to start.
* This is to protect deposit transactions already in mempool,
* and also make sure user only needs to SE within first week when invalid vault is registered.
* see: https://github.com/omisego/plasma-contracts/issues/412
* https://github.com/omisego/plasma-contracts/issues/173
*/
constructor(uint256 _minExitPeriod, uint256 _initialImmuneVaults)
public
{
_vaultQuarantine.quarantinePeriod = 2 * _minExitPeriod;
_vaultQuarantine.immunitiesRemaining = _initialImmuneVaults;
}
/**
* @notice interface to get the 'maintainer' address.
* @dev see discussion here: https://git.io/Je8is
*/
function getMaintainer() public view returns (address);
/**
* @notice A modifier to check that the call is from a non-quarantined vault
*/
modifier onlyFromNonQuarantinedVault() {
require(_vaultToId[msg.sender] > 0, "The call is not from a registered vault");
require(!_vaultQuarantine.isQuarantined(msg.sender), "Vault is quarantined");
_;
}
/**
* @notice Register a vault within the PlasmaFramework. Only a maintainer can make the call.
* @dev emits VaultRegistered event to notify clients
* @param _vaultId The ID for the vault contract to register
* @param _vaultAddress Address of the vault contract
*/
function registerVault(uint256 _vaultId, address _vaultAddress) public onlyFrom(getMaintainer()) {
require(_vaultId != 0, "Should not register with vault ID 0");
require(Address.isContract(_vaultAddress), "Should not register with a non-contract address");
require(_vaults[_vaultId] == address(0), "The vault ID is already registered");
require(_vaultToId[_vaultAddress] == 0, "The vault contract is already registered");
_vaults[_vaultId] = _vaultAddress;
_vaultToId[_vaultAddress] = _vaultId;
_vaultQuarantine.quarantine(_vaultAddress);
emit VaultRegistered(_vaultId, _vaultAddress);
}
/**
* @notice Public getter for retrieving vault address with vault ID
*/
function vaults(uint256 _vaultId) public view returns (address) {
return _vaults[_vaultId];
}
/**
* @notice Public getter for retrieving vault ID with vault address
*/
function vaultToId(address _vaultAddress) public view returns (uint256) {
return _vaultToId[_vaultAddress];
}
}pragma solidity 0.5.11;
import "../../utils/PosLib.sol";
library ExitPriority {
using PosLib for PosLib.Position;
/**
* @dev Returns an exit priority for a given UTXO position and a unique ID.
* The priority for Plasma M(ore)VP protocol is a combination of 'exitableAt' and 'txPos'.
* Since 'exitableAt' only provides granularity of block, add 'txPos' to provide priority for a transaction.
* @notice Detailed explanation on field lengths can be found at https://github.com/omisego/plasma-contracts/pull/303#discussion_r328850572
* @param exitId Unique exit identifier
* @return An exit priority
* Anatomy of returned value, most significant bits first
* 42 bits - timestamp in seconds (exitable_at); we can represent dates until year 141431
* 54 bits - blocknum * 10^5 + txindex; 54 bits represent all transactions for 85 years. Be aware that child chain block number jumps with the interval of CHILD_BLOCK_INTERVAL, which would be 1000 in production.
* 160 bits - exit id
*/
function computePriority(uint64 exitableAt, PosLib.Position memory txPos, uint160 exitId)
internal
pure
returns (uint256)
{
return (uint256(exitableAt) << 214) | (txPos.getTxPositionForExitPriority() << 160) | uint256(exitId);
}
function parseExitableAt(uint256 priority) internal pure returns (uint64) {
return uint64(priority >> 214);
}
function parseExitId(uint256 priority) internal pure returns (uint160) {
// Exit ID uses only 160 least significant bits
return uint160(priority);
}
}pragma solidity 0.5.11;
import "../../utils/OnlyFromAddress.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
/**
* @title PriorityQueue
* @dev Min-heap priority queue implementation
*/
contract PriorityQueue is OnlyFromAddress {
using SafeMath for uint256;
struct Queue {
uint256[] heapList;
uint256 currentSize;
}
Queue public queue;
address public framework;
constructor() public {
queue.heapList = [0];
queue.currentSize = 0;
// it is expected that this should be called by PlasmaFramework
// and only PlasmaFramework contract can add things to the queue
framework = msg.sender;
}
/**
* @notice Gets num of elements in the queue
*/
function currentSize() external view returns (uint256) {
return queue.currentSize;
}
/**
* @notice Gets all elements in the queue
*/
function heapList() external view returns (uint256[] memory) {
return queue.heapList;
}
/**
* @notice Inserts an element into the queue by the framework
* @dev Does not perform deduplication
*/
function insert(uint256 _element) external onlyFrom(framework) {
queue.heapList.push(_element);
queue.currentSize = queue.currentSize.add(1);
percUp(queue, queue.currentSize);
}
/**
* @notice Deletes the smallest element from the queue by the framework
* @dev Fails when queue is empty
* @return The smallest element in the priority queue
*/
function delMin() external onlyFrom(framework) returns (uint256) {
require(queue.currentSize > 0, "Queue is empty");
uint256 retVal = queue.heapList[1];
queue.heapList[1] = queue.heapList[queue.currentSize];
delete queue.heapList[queue.currentSize];
queue.currentSize = queue.currentSize.sub(1);
percDown(queue, 1);
queue.heapList.length = queue.heapList.length.sub(1);
return retVal;
}
/**
* @notice Returns the smallest element from the queue
* @dev Fails when queue is empty
* @return The smallest element in the priority queue
*/
function getMin() external view returns (uint256) {
require(queue.currentSize > 0, "Queue is empty");
return queue.heapList[1];
}
function percUp(Queue storage self, uint256 pointer) private {
uint256 i = pointer;
uint256 j = i;
uint256 newVal = self.heapList[i];
while (newVal < self.heapList[i.div(2)]) {
self.heapList[i] = self.heapList[i.div(2)];
i = i.div(2);
}
if (i != j) {
self.heapList[i] = newVal;
}
}
function percDown(Queue storage self, uint256 pointer) private {
uint256 i = pointer;
uint256 j = i;
uint256 newVal = self.heapList[i];
uint256 mc = minChild(self, i);
while (mc <= self.currentSize && newVal > self.heapList[mc]) {
self.heapList[i] = self.heapList[mc];
i = mc;
mc = minChild(self, i);
}
if (i != j) {
self.heapList[i] = newVal;
}
}
function minChild(Queue storage self, uint256 i) private view returns (uint256) {
if (i.mul(2).add(1) > self.currentSize) {
return i.mul(2);
} else {
if (self.heapList[i.mul(2)] < self.heapList[i.mul(2).add(1)]) {
return i.mul(2);
} else {
return i.mul(2).add(1);
}
}
}
}pragma solidity 0.5.11;
/**
* @notice Provides a way to quarantine (disable) contracts for a specified period of time
* @dev The immunitiesRemaining member allows deployment to the platform with some
* pre-verified contracts that don't get quarantined
*/
library Quarantine {
struct Data {
mapping(address => uint256) store;
uint256 quarantinePeriod;
uint256 immunitiesRemaining;
}
/**
* @notice Checks whether a contract is quarantined
*/
function isQuarantined(Data storage _self, address _contractAddress) internal view returns (bool) {
return block.timestamp < _self.store[_contractAddress];
}
/**
* @notice Places a contract into quarantine
* @param _contractAddress The address of the contract
*/
function quarantine(Data storage _self, address _contractAddress) internal {
require(_contractAddress != address(0), "An empty address cannot be quarantined");
require(_self.store[_contractAddress] == 0, "The contract is already quarantined");
if (_self.immunitiesRemaining == 0) {
_self.store[_contractAddress] = block.timestamp + _self.quarantinePeriod;
} else {
_self.immunitiesRemaining--;
}
}
}pragma solidity 0.5.11;
contract OnlyFromAddress {
modifier onlyFrom(address caller) {
require(msg.sender == caller, "Caller address is unauthorized");
_;
}
}pragma solidity 0.5.11;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
/**
* @dev UTXO position = (blknum * BLOCK_OFFSET + txIndex * TX_OFFSET + outputIndex).
* TX position = (blknum * BLOCK_OFFSET + txIndex * TX_OFFSET)
*/
library PosLib {
struct Position {
uint64 blockNum;
uint16 txIndex;
uint16 outputIndex;
}
uint256 constant internal BLOCK_OFFSET = 1000000000;
uint256 constant internal TX_OFFSET = 10000;
uint256 constant internal MAX_OUTPUT_INDEX = TX_OFFSET - 1;
// since we are using merkle tree of depth 16, max tx index size is 2^16 - 1
uint256 constant internal MAX_TX_INDEX = 2 ** 16 - 1;
// in ExitPriority, only 54 bits are reserved for both blockNum and txIndex
uint256 constant internal MAX_BLOCK_NUM = ((2 ** 54 - 1) - MAX_TX_INDEX) / (BLOCK_OFFSET / TX_OFFSET);
/**
* @notice Returns transaction position which is an utxo position of zero index output
* @param pos UTXO position of the output
* @return Position of a transaction
*/
function toStrictTxPos(Position memory pos)
internal
pure
returns (Position memory)
{
return Position(pos.blockNum, pos.txIndex, 0);
}
/**
* @notice Used for calculating exit priority
* @param pos UTXO position for the output
* @return Identifier of the transaction
*/
function getTxPositionForExitPriority(Position memory pos)
internal
pure
returns (uint256)
{
return encode(pos) / TX_OFFSET;
}
/**
* @notice Encodes a position
* @param pos Position
* @return Position encoded as an integer
*/
function encode(Position memory pos) internal pure returns (uint256) {
require(pos.outputIndex <= MAX_OUTPUT_INDEX, "Invalid output index");
require(pos.blockNum <= MAX_BLOCK_NUM, "Invalid block number");
return pos.blockNum * BLOCK_OFFSET + pos.txIndex * TX_OFFSET + pos.outputIndex;
}
/**
* @notice Decodes a position from an integer value
* @param pos Encoded position
* @return Position
*/
function decode(uint256 pos) internal pure returns (Position memory) {
uint256 blockNum = pos / BLOCK_OFFSET;
uint256 txIndex = (pos % BLOCK_OFFSET) / TX_OFFSET;
uint16 outputIndex = uint16(pos % TX_OFFSET);
require(blockNum <= MAX_BLOCK_NUM, "blockNum exceeds max size allowed in PlasmaFramework");
require(txIndex <= MAX_TX_INDEX, "txIndex exceeds the size of uint16");
return Position(uint64(blockNum), uint16(txIndex), outputIndex);
}
}pragma solidity 0.5.11;
import "../framework/PlasmaFramework.sol";
import "../utils/OnlyFromAddress.sol";
/**
* @notice Base contract for vault implementation
* @dev This is the functionality to swap "deposit verifier"
* Setting a new deposit verifier allows an upgrade to a new deposit tx type without upgrading the vault
*/
contract Vault is OnlyFromAddress {
byte private constant LEAF_SALT = 0x00;
byte private constant NODE_SALT = 0x01;
event SetDepositVerifierCalled(address nextDepositVerifier);
PlasmaFramework internal framework;
bytes32[16] internal zeroHashes; // Pre-computes zero hashes to be used for building merkle tree for deposit block
/**
* @notice Stores deposit verifier contract addresses; first contract address is effective until the
* `newDepositVerifierMaturityTimestamp`; second contract address becomes effective after that timestamp
*/
address[2] public depositVerifiers;
uint256 public newDepositVerifierMaturityTimestamp = 2 ** 255; // point far in the future
constructor(PlasmaFramework _framework) public {
framework = _framework;
zeroHashes = getZeroHashes();
}
/**
* @dev Pre-computes zero hashes to be used for building Merkle tree for deposit block
*/
function getZeroHashes() private pure returns (bytes32[16] memory) {
bytes32[16] memory hashes;
bytes32 zeroHash = keccak256(abi.encodePacked(LEAF_SALT, uint256(0)));
for (uint i = 0; i < 16; i++) {
hashes[i] = zeroHash;
zeroHash = keccak256(abi.encodePacked(NODE_SALT, zeroHash, zeroHash));
}
return hashes;
}
/**
* @notice Checks whether the call originates from a non-quarantined exit game contract
*/
modifier onlyFromNonQuarantinedExitGame() {
require(
ExitGameRegistry(framework).isExitGameSafeToUse(msg.sender),
"Called from a non-registered or quarantined exit game contract"
);
_;
}
/**
* @notice Sets the deposit verifier contract, which may be called only by the operator
* @dev emit SetDepositVerifierCalled
* @dev When one contract is already set, the next one is effective after 2 * MIN_EXIT_PERIOD.
* This is to protect deposit transactions already in mempool,
* and also make sure user only needs to SE within first week when invalid vault is registered.
*
* see: https://github.com/omisego/plasma-contracts/issues/412
* https://github.com/omisego/plasma-contracts/issues/173
*
* @param _verifier Address of the verifier contract
*/
function setDepositVerifier(address _verifier) public onlyFrom(framework.getMaintainer()) {
require(_verifier != address(0), "Cannot set an empty address as deposit verifier");
if (depositVerifiers[0] != address(0)) {
depositVerifiers[0] = getEffectiveDepositVerifier();
depositVerifiers[1] = _verifier;
newDepositVerifierMaturityTimestamp = now + 2 * framework.minExitPeriod();
} else {
depositVerifiers[0] = _verifier;
}
emit SetDepositVerifierCalled(_verifier);
}
/**
* @notice Retrieves the currently effective deposit verifier contract address
* @return Contract address of the deposit verifier
*/
function getEffectiveDepositVerifier() public view returns (address) {
if (now < newDepositVerifierMaturityTimestamp) {
return depositVerifiers[0];
} else {
return depositVerifiers[1];
}
}
/**
* @notice Generate and submit a deposit block root to the PlasmaFramework
* @dev Designed to be called by the contract that inherits Vault
*/
function submitDepositBlock(bytes memory depositTx) internal returns (uint256) {
bytes32 root = getDepositBlockRoot(depositTx);
uint256 depositBlkNum = framework.submitDepositBlock(root);
return depositBlkNum;
}
function getDepositBlockRoot(bytes memory depositTx) private view returns (bytes32) {
bytes32 root = keccak256(abi.encodePacked(LEAF_SALT, depositTx));
for (uint i = 0; i < 16; i++) {
root = keccak256(abi.encodePacked(NODE_SALT, root, zeroHashes[i]));
}
return root;
}
}pragma solidity 0.5.11;
interface IErc20DepositVerifier {
/**
* @notice Verifies a deposit transaction
* @param depositTx The deposit transaction
* @param sender The owner of the deposit transaction
* @param vault The address of the Erc20Vault contract
* @return Verified (owner, token, amount) of the deposit ERC20 token data
*/
function verify(bytes calldata depositTx, address sender, address vault)
external
view
returns (address owner, address token, uint256 amount);
}pragma solidity ^0.5.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}pragma solidity ^0.5.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see `ERC20Detailed`.
*/
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.
*
* > 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);
}pragma solidity ^0.5.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value);
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.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}pragma solidity ^0.5.0;
/**
* @dev Collection of functions related to the address type,
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* This test is non-exhaustive, and there may be false-negatives: during the
* execution of a contract's constructor, its address will be reported as
* not containing a contract.
*
* > It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"depositVerifiers","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_verifier","type":"address"}],"name":"setDepositVerifier","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getEffectiveDepositVerifier","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"depositTx","type":"bytes"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"newDepositVerifierMaturityTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract PlasmaFramework","name":"_framework","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Erc20Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":true,"internalType":"uint256","name":"blknum","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nextDepositVerifier","type":"address"}],"name":"SetDepositVerifierCalled","type":"event"}]Contract Creation Code
60806040527f800000000000000000000000000000000000000000000000000000000000000060135534801561003457600080fd5b5060405162000dc638038062000dc68339818101604052602081101561005957600080fd5b5051600080546001600160a01b0319166001600160a01b0383161790558061007f610095565b61008d90600190601061015b565b5050506101d2565b61009d610199565b6100a5610199565b6040805160006020808301829052602180840183905284518085039091018152604190930190935281519190920120905b601081101561015257818382601081106100ec57fe5b60209081029190910191909152604080517f010000000000000000000000000000000000000000000000000000000000000081840152602181018590526041808201959095528151808203909501855260610190528251920191909120906001016100d6565b50909150505b90565b8260108101928215610189579160200282015b8281111561018957825182559160200191906001019061016e565b506101959291506101b8565b5090565b6040518061020001604052806010906020820280388339509192915050565b61015891905b8082111561019557600081556001016101be565b610be480620001e26000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806302e9b07b146100675780632c6ce78b146100a057806352518b7f146100c857806398b1e06a146100d0578063a7e5994f14610140578063d9caed121461015a575b600080fd5b6100846004803603602081101561007d57600080fd5b5035610190565b604080516001600160a01b039092168252519081900360200190f35b6100c6600480360360208110156100b657600080fd5b50356001600160a01b03166101ad565b005b6100846103df565b6100c6600480360360208110156100e657600080fd5b81019060208101813564010000000081111561010157600080fd5b82018360208201111561011357600080fd5b8035906020019184600183028401116401000000008311171561013557600080fd5b50909250905061040e565b6101486105d7565b60408051918252519081900360200190f35b6100c66004803603606081101561017057600080fd5b506001600160a01b038135811691602081013590911690604001356105dd565b6011816002811061019d57fe5b01546001600160a01b0316905081565b6000809054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101fa57600080fd5b505afa15801561020e573d6000803e3d6000fd5b505050506040513d602081101561022457600080fd5b5051336001600160a01b03821614610283576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206164647265737320697320756e617574686f72697a65640000604482015290519081900360640190fd5b6001600160a01b0382166102c85760405162461bcd60e51b815260040180806020018281038252602f815260200180610af8602f913960400191505060405180910390fd5b6011546001600160a01b031615610383576102e16103df565b601180546001600160a01b03199081166001600160a01b0393841617909155601280549091168483161790556000546040805163d4a2b4ef60e01b81529051919092169163d4a2b4ef916004808301926020929190829003018186803b15801561034a57600080fd5b505afa15801561035e573d6000803e3d6000fd5b505050506040513d602081101561037457600080fd5b5051600202420160135561039f565b601180546001600160a01b0319166001600160a01b0384161790555b604080516001600160a01b038416815290517f11e5a7570e0de4b31179f8c9cf5e8a1e6cfd23731ec7a5a06e3006d71dd321fd9181900360200190a15050565b600060135442101561040257601160005b01546001600160a01b0316905061040b565b601160016103f0565b90565b60006104186103df565b90506001600160a01b03811661045f5760405162461bcd60e51b8152600401808060200182810382526021815260200180610b276021913960400191505060405180910390fd5b604051635970e69f60e11b81523360248201819052306044830181905260606004840190815260648401869052600093849384936001600160a01b0388169363b2e1cd3e938b938b93909290918190608401868680828437600081840152601f19601f8201169050808301925050509550505050505060606040518083038186803b1580156104ed57600080fd5b505afa158015610501573d6000803e3d6000fd5b505050506040513d606081101561051757600080fd5b508051602082015160409092015190945090925090506105486001600160a01b03831684308463ffffffff6106f916565b600061058987878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061075992505050565b6040805184815290519192506001600160a01b03851691839133917f18569122d84f30025bb8dffb33563f1bdbfb9637f21552b11b8305686e9cb3079181900360200190a450505050505050565b60135481565b60005460408051632d0816d760e11b815233600482015290516001600160a01b0390921691635a102dae91602480820192602092909190829003018186803b15801561062857600080fd5b505afa15801561063c573d6000803e3d6000fd5b505050506040513d602081101561065257600080fd5b505161068f5760405162461bcd60e51b815260040180806020018281038252603e815260200180610b72603e913960400191505060405180910390fd5b6106a96001600160a01b038316848363ffffffff6107eb16565b816001600160a01b0316836001600160a01b03167fcd43b20ab5058a2a0a057681c9d3754aa8971fe74dacc8b6e4be0a49dae13101836040518082815260200191505060405180910390a3505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610753908590610842565b50505050565b600080610765836109fa565b60008054604080516317cb58d360e31b815260048101859052905193945091926001600160a01b039091169163be5ac69891602480830192602092919082900301818787803b1580156107b757600080fd5b505af11580156107cb573d6000803e3d6000fd5b505050506040513d60208110156107e157600080fd5b5051949350505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261083d908490610842565b505050565b610854826001600160a01b0316610af1565b6108a5576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106108e35780518252601f1990920191602091820191016108c4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610945576040519150601f19603f3d011682016040523d82523d6000602084013e61094a565b606091505b5091509150816109a1576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610753578080602001905160208110156109bd57600080fd5b50516107535760405162461bcd60e51b815260040180806020018281038252602a815260200180610b48602a913960400191505060405180910390fd5b60405160006020808301828152845192938493849387939260210191908401908083835b60208310610a3d5780518252601f199092019160209182019101610a1e565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405280519060200120905060008090505b6010811015610aea57600160f81b8260018360108110610a9d57fe5b0154604080516001600160f81b0319909416602080860191909152602185019390935260418085019290925280518085039092018252606190930190925281519101209150600101610a81565b5092915050565b3b15159056fe43616e6e6f742073657420616e20656d7074792061646472657373206173206465706f7369742076657269666965724465706f73697420766572696669657220686173206e6f74206265656e207365745361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656443616c6c65642066726f6d2061206e6f6e2d72656769737465726564206f722071756172616e74696e656420657869742067616d6520636f6e7472616374a265627a7a72315820bd0d5bf30eb9c4359cd401c04e15380f4c2f6631d91a7548a31fa1ef85d18a5d64736f6c634300050b00320000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100625760003560e01c806302e9b07b146100675780632c6ce78b146100a057806352518b7f146100c857806398b1e06a146100d0578063a7e5994f14610140578063d9caed121461015a575b600080fd5b6100846004803603602081101561007d57600080fd5b5035610190565b604080516001600160a01b039092168252519081900360200190f35b6100c6600480360360208110156100b657600080fd5b50356001600160a01b03166101ad565b005b6100846103df565b6100c6600480360360208110156100e657600080fd5b81019060208101813564010000000081111561010157600080fd5b82018360208201111561011357600080fd5b8035906020019184600183028401116401000000008311171561013557600080fd5b50909250905061040e565b6101486105d7565b60408051918252519081900360200190f35b6100c66004803603606081101561017057600080fd5b506001600160a01b038135811691602081013590911690604001356105dd565b6011816002811061019d57fe5b01546001600160a01b0316905081565b6000809054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156101fa57600080fd5b505afa15801561020e573d6000803e3d6000fd5b505050506040513d602081101561022457600080fd5b5051336001600160a01b03821614610283576040805162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206164647265737320697320756e617574686f72697a65640000604482015290519081900360640190fd5b6001600160a01b0382166102c85760405162461bcd60e51b815260040180806020018281038252602f815260200180610af8602f913960400191505060405180910390fd5b6011546001600160a01b031615610383576102e16103df565b601180546001600160a01b03199081166001600160a01b0393841617909155601280549091168483161790556000546040805163d4a2b4ef60e01b81529051919092169163d4a2b4ef916004808301926020929190829003018186803b15801561034a57600080fd5b505afa15801561035e573d6000803e3d6000fd5b505050506040513d602081101561037457600080fd5b5051600202420160135561039f565b601180546001600160a01b0319166001600160a01b0384161790555b604080516001600160a01b038416815290517f11e5a7570e0de4b31179f8c9cf5e8a1e6cfd23731ec7a5a06e3006d71dd321fd9181900360200190a15050565b600060135442101561040257601160005b01546001600160a01b0316905061040b565b601160016103f0565b90565b60006104186103df565b90506001600160a01b03811661045f5760405162461bcd60e51b8152600401808060200182810382526021815260200180610b276021913960400191505060405180910390fd5b604051635970e69f60e11b81523360248201819052306044830181905260606004840190815260648401869052600093849384936001600160a01b0388169363b2e1cd3e938b938b93909290918190608401868680828437600081840152601f19601f8201169050808301925050509550505050505060606040518083038186803b1580156104ed57600080fd5b505afa158015610501573d6000803e3d6000fd5b505050506040513d606081101561051757600080fd5b508051602082015160409092015190945090925090506105486001600160a01b03831684308463ffffffff6106f916565b600061058987878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061075992505050565b6040805184815290519192506001600160a01b03851691839133917f18569122d84f30025bb8dffb33563f1bdbfb9637f21552b11b8305686e9cb3079181900360200190a450505050505050565b60135481565b60005460408051632d0816d760e11b815233600482015290516001600160a01b0390921691635a102dae91602480820192602092909190829003018186803b15801561062857600080fd5b505afa15801561063c573d6000803e3d6000fd5b505050506040513d602081101561065257600080fd5b505161068f5760405162461bcd60e51b815260040180806020018281038252603e815260200180610b72603e913960400191505060405180910390fd5b6106a96001600160a01b038316848363ffffffff6107eb16565b816001600160a01b0316836001600160a01b03167fcd43b20ab5058a2a0a057681c9d3754aa8971fe74dacc8b6e4be0a49dae13101836040518082815260200191505060405180910390a3505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610753908590610842565b50505050565b600080610765836109fa565b60008054604080516317cb58d360e31b815260048101859052905193945091926001600160a01b039091169163be5ac69891602480830192602092919082900301818787803b1580156107b757600080fd5b505af11580156107cb573d6000803e3d6000fd5b505050506040513d60208110156107e157600080fd5b5051949350505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261083d908490610842565b505050565b610854826001600160a01b0316610af1565b6108a5576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106108e35780518252601f1990920191602091820191016108c4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610945576040519150601f19603f3d011682016040523d82523d6000602084013e61094a565b606091505b5091509150816109a1576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610753578080602001905160208110156109bd57600080fd5b50516107535760405162461bcd60e51b815260040180806020018281038252602a815260200180610b48602a913960400191505060405180910390fd5b60405160006020808301828152845192938493849387939260210191908401908083835b60208310610a3d5780518252601f199092019160209182019101610a1e565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405280519060200120905060008090505b6010811015610aea57600160f81b8260018360108110610a9d57fe5b0154604080516001600160f81b0319909416602080860191909152602185019390935260418085019290925280518085039092018252606190930190925281519101209150600101610a81565b5092915050565b3b15159056fe43616e6e6f742073657420616e20656d7074792061646472657373206173206465706f7369742076657269666965724465706f73697420766572696669657220686173206e6f74206265656e207365745361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656443616c6c65642066726f6d2061206e6f6e2d72656769737465726564206f722071756172616e74696e656420657869742067616d6520636f6e7472616374a265627a7a72315820bd0d5bf30eb9c4359cd401c04e15380f4c2f6631d91a7548a31fa1ef85d18a5d64736f6c634300050b0032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac
-----Decoded View---------------
Arg [0] : _framework (address): 0x0D4C1222f5e839a911e2053860e45F18921D72ac
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac
Deployed Bytecode Sourcemap
273:1903:13:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;273:1903:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;922:34:14;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;922:34:14;;:::i;:::-;;;;-1:-1:-1;;;;;922:34:14;;;;;;;;;;;;;;2670:560;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2670:560:14;-1:-1:-1;;;;;2670:560:14;;:::i;:::-;;3391:240;;;:::i;1117:578:13:-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1117:578:13;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;1117:578:13;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;1117:578:13;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;1117:578:13;;-1:-1:-1;1117:578:13;-1:-1:-1;1117:578:13;:::i;962:61:14:-;;;:::i;:::-;;;;;;;;;;;;;;;;1944:230:13;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;1944:230:13;;;;;;;;;;;;;;;;;:::i;922:34:14:-;;;;;;;;;;;;-1:-1:-1;;;;;922:34:14;;-1:-1:-1;922:34:14;:::o;2670:560::-;2733:9;;;;;;;;;-1:-1:-1;;;;;2733:9:14;-1:-1:-1;;;;;2733:23:14;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2733:25:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2733:25:14;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2733:25:14;109:10:11;-1:-1:-1;;;;;109:20:11;;;101:63;;;;;-1:-1:-1;;;101:63:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2778:23:14;;2770:83;;;;-1:-1:-1;;;2770:83:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2868:16;:19;-1:-1:-1;;;;;2868:19:14;:33;2864:309;;2939:29;:27;:29::i;:::-;2917:16;:51;;-1:-1:-1;;;;;;2917:51:14;;;-1:-1:-1;;;;;2917:51:14;;;;;;;2982:19;:31;;;;;;;;;;;-1:-1:-1;3075:9:14;:25;;;-1:-1:-1;;;3075:25:14;;;;:9;;;;;:23;;:25;;;;;;;;;;;;;;:9;:25;;;5:2:-1;;;;30:1;27;20:12;5:2;3075:25:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3075:25:14;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3075:25:14;3071:1;:29;3065:3;:35;3027;:73;2864:309;;;3131:16;:31;;-1:-1:-1;;;;;;3131:31:14;-1:-1:-1;;;;;3131:31:14;;;;;2864:309;3188:35;;;-1:-1:-1;;;;;3188:35:14;;;;;;;;;;;;;;;2670:560;;:::o;3391:240::-;3451:7;3480:35;;3474:3;:41;3470:155;;;3538:16;3555:1;3538:19;;;-1:-1:-1;;;;;3538:19:14;;-1:-1:-1;3531:26:14;;3470:155;3595:16;3612:1;3595:19;;3470:155;3391:240;:::o;1117:578:13:-;1179:23;1205:35;:33;:35::i;:::-;1179:61;-1:-1:-1;;;;;;1258:29:13;;1250:75;;;;-1:-1:-1;;;1250:75:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1389:96;;-1:-1:-1;;;1389:96:13;;1459:10;1389:96;;;;;;1479:4;1389:96;;;;;;;;;;;;;;;;;;;1337:17;;;;;;-1:-1:-1;;;;;1389:58:13;;;;;1448:9;;;;1459:10;;1479:4;;1389:96;;;;1448:9;;;;1389:96;1:33:-1;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;1389:96:13;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1389:96:13;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1389:96:13;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1389:96:13;;;;;;;;;;;;;-1:-1:-1;1389:96:13;;-1:-1:-1;1389:96:13;-1:-1:-1;1496:64:13;-1:-1:-1;;;;;1496:30:13;;1389:96;1546:4;1389:96;1496:64;:30;:64;:::i;:::-;1571:14;1588:35;1613:9;;1588:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;1588:24:13;;-1:-1:-1;;;1588:35:13:i;:::-;1639:49;;;;;;;;1571:52;;-1:-1:-1;;;;;;1639:49:13;;;1571:52;;1654:10;;1639:49;;;;;;;;;1117:578;;;;;;;:::o;962:61:14:-;;;;:::o;1944:230:13:-;1875:9:14;;1858:59;;;-1:-1:-1;;;1858:59:14;;1906:10;1858:59;;;;;;-1:-1:-1;;;;;1875:9:14;;;;1858:47;;:59;;;;;;;;;;;;;;;1875:9;1858:59;;;5:2:-1;;;;30:1;27;20:12;5:2;1858:59:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1858:59:14;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1858:59:14;1837:168;;;;-1:-1:-1;;;1837:168:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2069:44:13;-1:-1:-1;;;;;2069:26:13;;2096:8;2106:6;2069:44;:26;:44;:::i;:::-;2153:5;-1:-1:-1;;;;;2128:39:13;2143:8;-1:-1:-1;;;;;2128:39:13;;2160:6;2128:39;;;;;;;;;;;;;;;;;;1944:230;;;:::o;842:202:18:-;968:68;;;-1:-1:-1;;;;;968:68:18;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;968:68:18;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;942:95:18;;961:5;;942:18;:95::i;:::-;842:202;;;;:::o;3802:240:14:-;3872:7;3891:12;3906:30;3926:9;3906:19;:30::i;:::-;3947:21;3971:9;;:34;;;-1:-1:-1;;;3971:34:14;;;;;;;;;;3891:45;;-1:-1:-1;3947:21:14;;-1:-1:-1;;;;;3971:9:14;;;;:28;;:34;;;;;;;;;;;;;;3947:21;3971:9;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;3971:34:14;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3971:34:14;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3971:34:14;;3802:240;-1:-1:-1;;;;3802:240:14:o;662:174:18:-;770:58;;;-1:-1:-1;;;;;770:58:18;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;770:58:18;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;744:85:18;;763:5;;744:18;:85::i;:::-;662:174;;;:::o;2621:1095::-;3216:27;3224:5;-1:-1:-1;;;;;3216:25:18;;:27::i;:::-;3208:71;;;;;-1:-1:-1;;;3208:71:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;3350:12;3364:23;3399:5;-1:-1:-1;;;;;3391:19:18;3411:4;3391:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;3391:25:18;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;3349:67:18;;;;3434:7;3426:52;;;;;-1:-1:-1;;;3426:52:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3493:17;;:21;3489:221;;3633:10;3622:30;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3622:30:18;3614:85;;;;-1:-1:-1;;;3614:85:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4048:316:14;4167:38;;4123:7;4167:38;;;;;;;;;4123:7;;;;;;4195:9;;4167:38;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;4167:38:14;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;4167:38:14;;;4157:49;;;;;;4142:64;;4221:6;4230:1;4221:10;;4216:121;4237:2;4233:1;:6;4216:121;;;-1:-1:-1;;;4305:4:14;456;4322:1;4311:13;;;;;;;;;4277:48;;;-1:-1:-1;;;;;;4277:48:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;4277:48:14;;;;;;;4267:59;;;;;;-1:-1:-1;4277:48:14;4241:3;4216:121;;;-1:-1:-1;4353:4:14;4048:316;-1:-1:-1;;4048:316:14:o;542:413:19:-;902:20;940:8;;;542:413::o
Loading...
Loading
Loading...
Loading
OVERVIEW
The vault containing ERC-20 deposited into the OMG Network.Net Worth in USD
$11,313.18
Net Worth in ETH
5.725858
Token Allocations
USDT
73.72%
WBTC
12.90%
HOBO
3.81%
Others
9.58%
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 73.72% | $0.999776 | 8,341.4829 | $8,339.61 | |
| ETH | 12.90% | $76,149 | 0.0192 | $1,458.99 | |
| ETH | 3.81% | $0.00 | 11,000 | $0.00 | |
| ETH | 2.39% | $0.005399 | 50,000 | $269.94 | |
| ETH | 2.05% | $1 | 232.3158 | $232.32 | |
| ETH | 1.87% | $0.059297 | 3,561.9712 | $211.21 | |
| ETH | 1.06% | $120.42 | 1 | $120.42 | |
| ETH | 0.88% | $1 | 100 | $100 | |
| ETH | 0.47% | $0.99962 | 53 | $52.98 | |
| ETH | 0.22% | $0.999063 | 25 | $24.98 | |
| ETH | 0.14% | $3,455.04 | 0.0045 | $15.55 | |
| ETH | 0.08% | $1 | 9.11 | $9.11 | |
| ETH | 0.08% | $0.000056 | 161,694.7709 | $8.98 | |
| ETH | 0.07% | $0.076649 | 98.7 | $7.57 | |
| ETH | 0.06% | $0.120179 | 55 | $6.61 | |
| ETH | 0.05% | $8.86 | 0.7 | $6.2 | |
| ETH | 0.05% | $0.025317 | 235.3619 | $5.96 | |
| ETH | 0.04% | $0.10869 | 42 | $4.56 | |
| ETH | 0.02% | $189.03 | 0.0115 | $2.16 | |
| ETH | 0.01% | $0.288213 | 4.19 | $1.21 | |
| ETH | 0.01% | $0.032688 | 35 | $1.14 | |
| ETH | <0.01% | $0.0009 | 1,000 | $0.90 | |
| ETH | <0.01% | $0.000027 | 30,576.8 | $0.8384 | |
| ETH | <0.01% | $0.009228 | 60 | $0.5536 | |
| ETH | <0.01% | $0.1382 | 2.7 | $0.3731 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.