Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 10,336 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Epoch | 22541250 | 18 mins ago | IN | 0 ETH | 0.0008421 | ||||
Refund | 22468926 | 10 days ago | IN | 0 ETH | 0.00153981 | ||||
Refund | 22304685 | 33 days ago | IN | 0 ETH | 0.00013984 | ||||
Deregister | 22248404 | 41 days ago | IN | 0 ETH | 0.00004897 | ||||
Refund | 22240671 | 42 days ago | IN | 0 ETH | 0.00012593 | ||||
Deregister | 22224823 | 44 days ago | IN | 0 ETH | 0.00021859 | ||||
Deregister | 22224803 | 44 days ago | IN | 0 ETH | 0.00023575 | ||||
Deregister | 22224784 | 44 days ago | IN | 0 ETH | 0.00024005 | ||||
Deregister | 22187416 | 49 days ago | IN | 0 ETH | 0.00017784 | ||||
Deregister | 22187392 | 49 days ago | IN | 0 ETH | 0.0001799 | ||||
Deregister | 22187390 | 49 days ago | IN | 0 ETH | 0.00016482 | ||||
Deregister | 22187382 | 49 days ago | IN | 0 ETH | 0.00016994 | ||||
Deregister | 22175667 | 51 days ago | IN | 0 ETH | 0.00017627 | ||||
Refund | 22145575 | 55 days ago | IN | 0 ETH | 0.00013037 | ||||
Refund | 22138679 | 56 days ago | IN | 0 ETH | 0.00024654 | ||||
Refund | 22138677 | 56 days ago | IN | 0 ETH | 0.00023723 | ||||
Refund | 22138672 | 56 days ago | IN | 0 ETH | 0.0002327 | ||||
Refund | 22138669 | 56 days ago | IN | 0 ETH | 0.0002331 | ||||
Refund | 22138665 | 56 days ago | IN | 0 ETH | 0.00022292 | ||||
Refund | 22138659 | 56 days ago | IN | 0 ETH | 0.00021874 | ||||
Refund | 22138653 | 56 days ago | IN | 0 ETH | 0.00023555 | ||||
Refund | 22138649 | 56 days ago | IN | 0 ETH | 0.00020574 | ||||
Refund | 22138642 | 56 days ago | IN | 0 ETH | 0.00024165 | ||||
Refund | 22138639 | 56 days ago | IN | 0 ETH | 0.00025702 | ||||
Refund | 22138635 | 56 days ago | IN | 0 ETH | 0.00024367 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
DarknodeRegistryProxy
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-03-25 */ /** Deployed by Ren Project, https://renproject.io Commit hash: 9068f80 Repository: https://github.com/renproject/darknode-sol Issues: https://github.com/renproject/darknode-sol/issues Licenses @openzeppelin/contracts: (MIT) https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/LICENSE darknode-sol: (GNU GPL V3) https://github.com/renproject/darknode-sol/blob/master/LICENSE */ pragma solidity 0.5.16; library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; return c; } function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } contract Proxy { function () payable external { _fallback(); } function _implementation() internal view returns (address); function _delegate(address implementation) internal { assembly { calldatacopy(0, 0, calldatasize) let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) returndatacopy(0, 0, returndatasize) switch result case 0 { revert(0, returndatasize) } default { return(0, returndatasize) } } } function _willFallback() internal { } function _fallback() internal { _willFallback(); _delegate(_implementation()); } } library OpenZeppelinUpgradesAddress { function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } } contract BaseUpgradeabilityProxy is Proxy { event Upgraded(address indexed implementation); bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; function _implementation() internal view returns (address impl) { bytes32 slot = IMPLEMENTATION_SLOT; assembly { impl := sload(slot) } } function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } function _setImplementation(address newImplementation) internal { require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address"); bytes32 slot = IMPLEMENTATION_SLOT; assembly { sstore(slot, newImplementation) } } } contract UpgradeabilityProxy is BaseUpgradeabilityProxy { constructor(address _logic, bytes memory _data) public payable { assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)); _setImplementation(_logic); if(_data.length > 0) { (bool success,) = _logic.delegatecall(_data); require(success); } } } contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy { event AdminChanged(address previousAdmin, address newAdmin); bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; modifier ifAdmin() { if (msg.sender == _admin()) { _; } else { _fallback(); } } function admin() external ifAdmin returns (address) { return _admin(); } function implementation() external ifAdmin returns (address) { return _implementation(); } function changeAdmin(address newAdmin) external ifAdmin { require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address"); emit AdminChanged(_admin(), newAdmin); _setAdmin(newAdmin); } function upgradeTo(address newImplementation) external ifAdmin { _upgradeTo(newImplementation); } function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin { _upgradeTo(newImplementation); (bool success,) = newImplementation.delegatecall(data); require(success); } function _admin() internal view returns (address adm) { bytes32 slot = ADMIN_SLOT; assembly { adm := sload(slot) } } function _setAdmin(address newAdmin) internal { bytes32 slot = ADMIN_SLOT; assembly { sstore(slot, newAdmin) } } function _willFallback() internal { require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin"); super._willFallback(); } } contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy { function initialize(address _logic, bytes memory _data) public payable { require(_implementation() == address(0)); assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)); _setImplementation(_logic); if(_data.length > 0) { (bool success,) = _logic.delegatecall(_data); require(success); } } } contract InitializableAdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, InitializableUpgradeabilityProxy { function initialize(address _logic, address _admin, bytes memory _data) public payable { require(_implementation() == address(0)); InitializableUpgradeabilityProxy.initialize(_logic, _data); assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)); _setAdmin(_admin); } } contract Initializable { bool private initialized; bool private initializing; modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } function isConstructor() private view returns (bool) { address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } uint256[50] private ______gap; } contract Context is Initializable { constructor () internal { } function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; return msg.data; } } contract Ownable is Initializable, Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function initialize(address sender) public initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } function owner() public view returns (address) { return _owner; } modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } function isOwner() public view returns (bool) { return _msgSender() == _owner; } function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; } interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } contract ERC20Detailed is Initializable, IERC20 { string private _name; string private _symbol; uint8 private _decimals; function initialize(string memory name, string memory symbol, uint8 decimals) public initializer { _name = name; _symbol = symbol; _decimals = decimals; } function name() public view returns (string memory) { return _name; } function symbol() public view returns (string memory) { return _symbol; } function decimals() public view returns (uint8) { return _decimals; } uint256[50] private ______gap; } contract ERC20 is Initializable, Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; function totalSupply() public view returns (uint256) { return _totalSupply; } function balanceOf(address account) public view returns (uint256) { return _balances[account]; } function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } function _transfer(address sender, address recipient, uint256 amount) internal { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } function _mint(address account, uint256 amount) internal { require(account != address(0), "ERC20: mint to the zero address"); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } function _burn(address account, uint256 amount) internal { require(account != address(0), "ERC20: burn from the zero address"); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } function _approve(address owner, address spender, uint256 amount) internal { 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); } function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } uint256[50] private ______gap; } library Roles { struct Role { mapping (address => bool) bearer; } function add(Role storage role, address account) internal { require(!has(role, account), "Roles: account already has role"); role.bearer[account] = true; } function remove(Role storage role, address account) internal { require(has(role, account), "Roles: account does not have role"); role.bearer[account] = false; } function has(Role storage role, address account) internal view returns (bool) { require(account != address(0), "Roles: account is the zero address"); return role.bearer[account]; } } contract PauserRole is Initializable, Context { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; function initialize(address sender) public initializer { if (!isPauser(sender)) { _addPauser(sender); } } modifier onlyPauser() { require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role"); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(_msgSender()); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } uint256[50] private ______gap; } contract Pausable is Initializable, Context, PauserRole { event Paused(address account); event Unpaused(address account); bool private _paused; function initialize(address sender) public initializer { PauserRole.initialize(sender); _paused = false; } function paused() public view returns (bool) { return _paused; } modifier whenNotPaused() { require(!_paused, "Pausable: paused"); _; } modifier whenPaused() { require(_paused, "Pausable: not paused"); _; } function pause() public onlyPauser whenNotPaused { _paused = true; emit Paused(_msgSender()); } function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(_msgSender()); } uint256[50] private ______gap; } contract ERC20Pausable is Initializable, ERC20, Pausable { function initialize(address sender) public initializer { Pausable.initialize(sender); } function transfer(address to, uint256 value) public whenNotPaused returns (bool) { return super.transfer(to, value); } function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) { return super.transferFrom(from, to, value); } function approve(address spender, uint256 value) public whenNotPaused returns (bool) { return super.approve(spender, value); } function increaseAllowance(address spender, uint256 addedValue) public whenNotPaused returns (bool) { return super.increaseAllowance(spender, addedValue); } function decreaseAllowance(address spender, uint256 subtractedValue) public whenNotPaused returns (bool) { return super.decreaseAllowance(spender, subtractedValue); } uint256[50] private ______gap; } contract ERC20Burnable is Initializable, Context, ERC20 { function burn(uint256 amount) public { _burn(_msgSender(), amount); } function burnFrom(address account, uint256 amount) public { _burnFrom(account, amount); } uint256[50] private ______gap; } contract RenToken is Ownable, ERC20Detailed, ERC20Pausable, ERC20Burnable { string private constant _name = "REN"; string private constant _symbol = "REN"; uint8 private constant _decimals = 18; uint256 public constant INITIAL_SUPPLY = 1000000000 * 10**uint256(_decimals); constructor() public { ERC20Pausable.initialize(msg.sender); ERC20Detailed.initialize(_name, _symbol, _decimals); Ownable.initialize(msg.sender); _mint(msg.sender, INITIAL_SUPPLY); } function transferTokens(address beneficiary, uint256 amount) public onlyOwner returns (bool) { require(amount > 0); _transfer(msg.sender, beneficiary, amount); emit Transfer(msg.sender, beneficiary, amount); return true; } } contract Claimable is Initializable, Ownable { address public pendingOwner; function initialize(address _nextOwner) public initializer { Ownable.initialize(_nextOwner); } modifier onlyPendingOwner() { require( _msgSender() == pendingOwner, "Claimable: caller is not the pending owner" ); _; } function transferOwnership(address newOwner) public onlyOwner { require( newOwner != owner() && newOwner != pendingOwner, "Claimable: invalid new owner" ); pendingOwner = newOwner; } function claimOwnership() public onlyPendingOwner { _transferOwnership(pendingOwner); delete pendingOwner; } } library LinkedList { address public constant NULL = address(0); struct Node { bool inList; address previous; address next; } struct List { mapping (address => Node) list; } function insertBefore(List storage self, address target, address newNode) internal { require(newNode != address(0), "LinkedList: invalid address"); require(!isInList(self, newNode), "LinkedList: already in list"); require(isInList(self, target) || target == NULL, "LinkedList: not in list"); address prev = self.list[target].previous; self.list[newNode].next = target; self.list[newNode].previous = prev; self.list[target].previous = newNode; self.list[prev].next = newNode; self.list[newNode].inList = true; } function insertAfter(List storage self, address target, address newNode) internal { require(newNode != address(0), "LinkedList: invalid address"); require(!isInList(self, newNode), "LinkedList: already in list"); require(isInList(self, target) || target == NULL, "LinkedList: not in list"); address n = self.list[target].next; self.list[newNode].previous = target; self.list[newNode].next = n; self.list[target].next = newNode; self.list[n].previous = newNode; self.list[newNode].inList = true; } function remove(List storage self, address node) internal { require(isInList(self, node), "LinkedList: not in list"); address p = self.list[node].previous; address n = self.list[node].next; self.list[p].next = n; self.list[n].previous = p; self.list[node].inList = false; delete self.list[node]; } function prepend(List storage self, address node) internal { insertBefore(self, begin(self), node); } function append(List storage self, address node) internal { insertAfter(self, end(self), node); } function swap(List storage self, address left, address right) internal { address previousRight = self.list[right].previous; remove(self, right); insertAfter(self, left, right); remove(self, left); insertAfter(self, previousRight, left); } function isInList(List storage self, address node) internal view returns (bool) { return self.list[node].inList; } function begin(List storage self) internal view returns (address) { return self.list[NULL].next; } function end(List storage self) internal view returns (address) { return self.list[NULL].previous; } function next(List storage self, address node) internal view returns (address) { require(isInList(self, node), "LinkedList: not in list"); return self.list[node].next; } function previous(List storage self, address node) internal view returns (address) { require(isInList(self, node), "LinkedList: not in list"); return self.list[node].previous; } function elements(List storage self, address _start, uint256 _count) internal view returns (address[] memory) { require(_count > 0, "LinkedList: invalid count"); require(isInList(self, _start) || _start == address(0), "LinkedList: not in list"); address[] memory elems = new address[](_count); uint256 n = 0; address nextItem = _start; if (nextItem == address(0)) { nextItem = begin(self); } while (n < _count) { if (nextItem == address(0)) { break; } elems[n] = nextItem; nextItem = next(self, nextItem); n += 1; } return elems; } } library Address { function isContract(address account) internal view returns (bool) { bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; assembly { codehash := extcodehash(account) } return (codehash != 0x0 && codehash != accountHash); } function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } 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"); } } 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 { require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function callOptionalReturn(IERC20 token, bytes memory data) private { require(address(token).isContract(), "SafeERC20: call to non-contract"); (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } contract CanReclaimTokens is Claimable { using SafeERC20 for ERC20; mapping(address => bool) private recoverableTokensBlacklist; function initialize(address _nextOwner) public initializer { Claimable.initialize(_nextOwner); } function blacklistRecoverableToken(address _token) public onlyOwner { recoverableTokensBlacklist[_token] = true; } function recoverTokens(address _token) external onlyOwner { require( !recoverableTokensBlacklist[_token], "CanReclaimTokens: token is not recoverable" ); if (_token == address(0x0)) { msg.sender.transfer(address(this).balance); } else { ERC20(_token).safeTransfer( msg.sender, ERC20(_token).balanceOf(address(this)) ); } } } contract DarknodeRegistryStore is Claimable, CanReclaimTokens { using SafeMath for uint256; string public VERSION; struct Darknode { address payable owner; uint256 bond; uint256 registeredAt; uint256 deregisteredAt; bytes publicKey; } mapping(address => Darknode) private darknodeRegistry; LinkedList.List private darknodes; RenToken public ren; constructor(string memory _VERSION, RenToken _ren) public { Claimable.initialize(msg.sender); CanReclaimTokens.initialize(msg.sender); VERSION = _VERSION; ren = _ren; blacklistRecoverableToken(address(ren)); } function appendDarknode( address _darknodeID, address payable _darknodeOperator, uint256 _bond, bytes calldata _publicKey, uint256 _registeredAt, uint256 _deregisteredAt ) external onlyOwner { Darknode memory darknode = Darknode({ owner: _darknodeOperator, bond: _bond, publicKey: _publicKey, registeredAt: _registeredAt, deregisteredAt: _deregisteredAt }); darknodeRegistry[_darknodeID] = darknode; LinkedList.append(darknodes, _darknodeID); } function begin() external view onlyOwner returns (address) { return LinkedList.begin(darknodes); } function next(address darknodeID) external view onlyOwner returns (address) { return LinkedList.next(darknodes, darknodeID); } function removeDarknode(address darknodeID) external onlyOwner { uint256 bond = darknodeRegistry[darknodeID].bond; delete darknodeRegistry[darknodeID]; LinkedList.remove(darknodes, darknodeID); require( ren.transfer(owner(), bond), "DarknodeRegistryStore: bond transfer failed" ); } function updateDarknodeBond(address darknodeID, uint256 decreasedBond) external onlyOwner { uint256 previousBond = darknodeRegistry[darknodeID].bond; require( decreasedBond < previousBond, "DarknodeRegistryStore: bond not decreased" ); darknodeRegistry[darknodeID].bond = decreasedBond; require( ren.transfer(owner(), previousBond.sub(decreasedBond)), "DarknodeRegistryStore: bond transfer failed" ); } function updateDarknodeDeregisteredAt( address darknodeID, uint256 deregisteredAt ) external onlyOwner { darknodeRegistry[darknodeID].deregisteredAt = deregisteredAt; } function darknodeOperator(address darknodeID) external view onlyOwner returns (address payable) { return darknodeRegistry[darknodeID].owner; } function darknodeBond(address darknodeID) external view onlyOwner returns (uint256) { return darknodeRegistry[darknodeID].bond; } function darknodeRegisteredAt(address darknodeID) external view onlyOwner returns (uint256) { return darknodeRegistry[darknodeID].registeredAt; } function darknodeDeregisteredAt(address darknodeID) external view onlyOwner returns (uint256) { return darknodeRegistry[darknodeID].deregisteredAt; } function darknodePublicKey(address darknodeID) external view onlyOwner returns (bytes memory) { return darknodeRegistry[darknodeID].publicKey; } } interface IDarknodePaymentStore {} interface IDarknodePayment { function changeCycle() external returns (uint256); function store() external view returns (IDarknodePaymentStore); } interface IDarknodeSlasher {} contract DarknodeRegistryStateV1 { using SafeMath for uint256; string public VERSION; struct Epoch { uint256 epochhash; uint256 blocktime; } uint256 public numDarknodes; uint256 public numDarknodesNextEpoch; uint256 public numDarknodesPreviousEpoch; uint256 public minimumBond; uint256 public minimumPodSize; uint256 public minimumEpochInterval; uint256 public deregistrationInterval; uint256 public nextMinimumBond; uint256 public nextMinimumPodSize; uint256 public nextMinimumEpochInterval; Epoch public currentEpoch; Epoch public previousEpoch; RenToken public ren; DarknodeRegistryStore public store; IDarknodePayment public darknodePayment; IDarknodeSlasher public slasher; IDarknodeSlasher public nextSlasher; } contract DarknodeRegistryLogicV1 is Claimable, CanReclaimTokens, DarknodeRegistryStateV1 { event LogDarknodeRegistered( address indexed _darknodeOperator, address indexed _darknodeID, uint256 _bond ); event LogDarknodeDeregistered( address indexed _darknodeOperator, address indexed _darknodeID ); event LogDarknodeRefunded( address indexed _darknodeOperator, address indexed _darknodeID, uint256 _amount ); event LogDarknodeSlashed( address indexed _darknodeOperator, address indexed _darknodeID, address indexed _challenger, uint256 _percentage ); event LogNewEpoch(uint256 indexed epochhash); event LogMinimumBondUpdated( uint256 _previousMinimumBond, uint256 _nextMinimumBond ); event LogMinimumPodSizeUpdated( uint256 _previousMinimumPodSize, uint256 _nextMinimumPodSize ); event LogMinimumEpochIntervalUpdated( uint256 _previousMinimumEpochInterval, uint256 _nextMinimumEpochInterval ); event LogSlasherUpdated( address indexed _previousSlasher, address indexed _nextSlasher ); event LogDarknodePaymentUpdated( IDarknodePayment indexed _previousDarknodePayment, IDarknodePayment indexed _nextDarknodePayment ); modifier onlyDarknodeOperator(address _darknodeID) { require( store.darknodeOperator(_darknodeID) == msg.sender, "DarknodeRegistry: must be darknode owner" ); _; } modifier onlyRefunded(address _darknodeID) { require( isRefunded(_darknodeID), "DarknodeRegistry: must be refunded or never registered" ); _; } modifier onlyRefundable(address _darknodeID) { require( isRefundable(_darknodeID), "DarknodeRegistry: must be deregistered for at least one epoch" ); _; } modifier onlyDeregisterable(address _darknodeID) { require( isDeregisterable(_darknodeID), "DarknodeRegistry: must be deregisterable" ); _; } modifier onlySlasher() { require( address(slasher) == msg.sender, "DarknodeRegistry: must be slasher" ); _; } modifier onlyDarknode(address _darknodeID) { require( isRegistered(_darknodeID), "DarknodeRegistry: invalid darknode" ); _; } function initialize( string memory _VERSION, RenToken _renAddress, DarknodeRegistryStore _storeAddress, uint256 _minimumBond, uint256 _minimumPodSize, uint256 _minimumEpochIntervalSeconds, uint256 _deregistrationIntervalSeconds ) public initializer { Claimable.initialize(msg.sender); CanReclaimTokens.initialize(msg.sender); VERSION = _VERSION; store = _storeAddress; ren = _renAddress; minimumBond = _minimumBond; nextMinimumBond = minimumBond; minimumPodSize = _minimumPodSize; nextMinimumPodSize = minimumPodSize; minimumEpochInterval = _minimumEpochIntervalSeconds; nextMinimumEpochInterval = minimumEpochInterval; deregistrationInterval = _deregistrationIntervalSeconds; uint256 epochhash = uint256(blockhash(block.number - 1)); currentEpoch = Epoch({ epochhash: epochhash, blocktime: block.timestamp }); emit LogNewEpoch(epochhash); } function register(address _darknodeID, bytes calldata _publicKey) external onlyRefunded(_darknodeID) { require( _darknodeID != address(0), "DarknodeRegistry: darknode address cannot be zero" ); require( ren.transferFrom(msg.sender, address(store), minimumBond), "DarknodeRegistry: bond transfer failed" ); store.appendDarknode( _darknodeID, msg.sender, minimumBond, _publicKey, currentEpoch.blocktime.add(minimumEpochInterval), 0 ); numDarknodesNextEpoch = numDarknodesNextEpoch.add(1); emit LogDarknodeRegistered(msg.sender, _darknodeID, minimumBond); } function deregister(address _darknodeID) external onlyDeregisterable(_darknodeID) onlyDarknodeOperator(_darknodeID) { deregisterDarknode(_darknodeID); } function epoch() external { if (previousEpoch.blocktime == 0) { require( msg.sender == owner(), "DarknodeRegistry: not authorized to call first epoch" ); } require( block.timestamp >= currentEpoch.blocktime.add(minimumEpochInterval), "DarknodeRegistry: epoch interval has not passed" ); uint256 epochhash = uint256(blockhash(block.number - 1)); previousEpoch = currentEpoch; currentEpoch = Epoch({ epochhash: epochhash, blocktime: block.timestamp }); numDarknodesPreviousEpoch = numDarknodes; numDarknodes = numDarknodesNextEpoch; if (nextMinimumBond != minimumBond) { minimumBond = nextMinimumBond; emit LogMinimumBondUpdated(minimumBond, nextMinimumBond); } if (nextMinimumPodSize != minimumPodSize) { minimumPodSize = nextMinimumPodSize; emit LogMinimumPodSizeUpdated(minimumPodSize, nextMinimumPodSize); } if (nextMinimumEpochInterval != minimumEpochInterval) { minimumEpochInterval = nextMinimumEpochInterval; emit LogMinimumEpochIntervalUpdated( minimumEpochInterval, nextMinimumEpochInterval ); } if (nextSlasher != slasher) { slasher = nextSlasher; emit LogSlasherUpdated(address(slasher), address(nextSlasher)); } if (address(darknodePayment) != address(0x0)) { darknodePayment.changeCycle(); } emit LogNewEpoch(epochhash); } function transferStoreOwnership(DarknodeRegistryLogicV1 _newOwner) external onlyOwner { store.transferOwnership(address(_newOwner)); _newOwner.claimStoreOwnership(); } function claimStoreOwnership() external { store.claimOwnership(); ( numDarknodesPreviousEpoch, numDarknodes, numDarknodesNextEpoch ) = getDarknodeCountFromEpochs(); } function updateDarknodePayment(IDarknodePayment _darknodePayment) external onlyOwner { require( address(_darknodePayment) != address(0x0), "DarknodeRegistry: invalid Darknode Payment address" ); IDarknodePayment previousDarknodePayment = darknodePayment; darknodePayment = _darknodePayment; emit LogDarknodePaymentUpdated( previousDarknodePayment, darknodePayment ); } function updateMinimumBond(uint256 _nextMinimumBond) external onlyOwner { nextMinimumBond = _nextMinimumBond; } function updateMinimumPodSize(uint256 _nextMinimumPodSize) external onlyOwner { nextMinimumPodSize = _nextMinimumPodSize; } function updateMinimumEpochInterval(uint256 _nextMinimumEpochInterval) external onlyOwner { nextMinimumEpochInterval = _nextMinimumEpochInterval; } function updateSlasher(IDarknodeSlasher _slasher) external onlyOwner { require( address(_slasher) != address(0), "DarknodeRegistry: invalid slasher address" ); nextSlasher = _slasher; } function slash(address _guilty, address _challenger, uint256 _percentage) external onlySlasher onlyDarknode(_guilty) { require(_percentage <= 100, "DarknodeRegistry: invalid percent"); if (isDeregisterable(_guilty)) { deregisterDarknode(_guilty); } uint256 totalBond = store.darknodeBond(_guilty); uint256 penalty = totalBond.div(100).mul(_percentage); uint256 challengerReward = penalty.div(2); uint256 darknodePaymentReward = penalty.sub(challengerReward); if (challengerReward > 0) { store.updateDarknodeBond(_guilty, totalBond.sub(penalty)); require( address(darknodePayment) != address(0x0), "DarknodeRegistry: invalid payment address" ); require( ren.transfer( address(darknodePayment.store()), darknodePaymentReward ), "DarknodeRegistry: reward transfer failed" ); require( ren.transfer(_challenger, challengerReward), "DarknodeRegistry: reward transfer failed" ); } emit LogDarknodeSlashed( store.darknodeOperator(_guilty), _guilty, _challenger, _percentage ); } function refund(address _darknodeID) external onlyRefundable(_darknodeID) { address darknodeOperator = store.darknodeOperator(_darknodeID); uint256 amount = store.darknodeBond(_darknodeID); store.removeDarknode(_darknodeID); require( ren.transfer(darknodeOperator, amount), "DarknodeRegistry: bond transfer failed" ); emit LogDarknodeRefunded(darknodeOperator, _darknodeID, amount); } function getDarknodeOperator(address _darknodeID) external view returns (address payable) { return store.darknodeOperator(_darknodeID); } function getDarknodeBond(address _darknodeID) external view returns (uint256) { return store.darknodeBond(_darknodeID); } function getDarknodePublicKey(address _darknodeID) external view returns (bytes memory) { return store.darknodePublicKey(_darknodeID); } function getDarknodes(address _start, uint256 _count) external view returns (address[] memory) { uint256 count = _count; if (count == 0) { count = numDarknodes; } return getDarknodesFromEpochs(_start, count, false); } function getPreviousDarknodes(address _start, uint256 _count) external view returns (address[] memory) { uint256 count = _count; if (count == 0) { count = numDarknodesPreviousEpoch; } return getDarknodesFromEpochs(_start, count, true); } function isPendingRegistration(address _darknodeID) public view returns (bool) { uint256 registeredAt = store.darknodeRegisteredAt(_darknodeID); return registeredAt != 0 && registeredAt > currentEpoch.blocktime; } function isPendingDeregistration(address _darknodeID) public view returns (bool) { uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID); return deregisteredAt != 0 && deregisteredAt > currentEpoch.blocktime; } function isDeregistered(address _darknodeID) public view returns (bool) { uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID); return deregisteredAt != 0 && deregisteredAt <= currentEpoch.blocktime; } function isDeregisterable(address _darknodeID) public view returns (bool) { uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID); return isRegistered(_darknodeID) && deregisteredAt == 0; } function isRefunded(address _darknodeID) public view returns (bool) { uint256 registeredAt = store.darknodeRegisteredAt(_darknodeID); uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID); return registeredAt == 0 && deregisteredAt == 0; } function isRefundable(address _darknodeID) public view returns (bool) { return isDeregistered(_darknodeID) && store.darknodeDeregisteredAt(_darknodeID) <= (previousEpoch.blocktime - deregistrationInterval); } function isRegistered(address _darknodeID) public view returns (bool) { return isRegisteredInEpoch(_darknodeID, currentEpoch); } function isRegisteredInPreviousEpoch(address _darknodeID) public view returns (bool) { return isRegisteredInEpoch(_darknodeID, previousEpoch); } function isRegisteredInEpoch(address _darknodeID, Epoch memory _epoch) private view returns (bool) { uint256 registeredAt = store.darknodeRegisteredAt(_darknodeID); uint256 deregisteredAt = store.darknodeDeregisteredAt(_darknodeID); bool registered = registeredAt != 0 && registeredAt <= _epoch.blocktime; bool notDeregistered = deregisteredAt == 0 || deregisteredAt > _epoch.blocktime; return registered && notDeregistered; } function getDarknodesFromEpochs( address _start, uint256 _count, bool _usePreviousEpoch ) private view returns (address[] memory) { uint256 count = _count; if (count == 0) { count = numDarknodes; } address[] memory nodes = new address[](count); uint256 n = 0; address next = _start; if (next == address(0)) { next = store.begin(); } while (n < count) { if (next == address(0)) { break; } bool includeNext; if (_usePreviousEpoch) { includeNext = isRegisteredInPreviousEpoch(next); } else { includeNext = isRegistered(next); } if (!includeNext) { next = store.next(next); continue; } nodes[n] = next; next = store.next(next); n += 1; } return nodes; } function deregisterDarknode(address _darknodeID) private { address darknodeOperator = store.darknodeOperator(_darknodeID); store.updateDarknodeDeregisteredAt( _darknodeID, currentEpoch.blocktime.add(minimumEpochInterval) ); numDarknodesNextEpoch = numDarknodesNextEpoch.sub(1); emit LogDarknodeDeregistered(darknodeOperator, _darknodeID); } function getDarknodeCountFromEpochs() private view returns (uint256, uint256, uint256) { uint256 nPreviousEpoch = 0; uint256 nCurrentEpoch = 0; uint256 nNextEpoch = 0; address next = store.begin(); while (true) { if (next == address(0)) { break; } if (isRegisteredInPreviousEpoch(next)) { nPreviousEpoch += 1; } if (isRegistered(next)) { nCurrentEpoch += 1; } if ( ((isRegistered(next) && !isPendingDeregistration(next)) || isPendingRegistration(next)) ) { nNextEpoch += 1; } next = store.next(next); } return (nPreviousEpoch, nCurrentEpoch, nNextEpoch); } } contract DarknodeRegistryProxy is InitializableAdminUpgradeabilityProxy {}
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initialize","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initialize","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"payable":true,"stateMutability":"payable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061097c806100206000396000f3fe6080604052600436106100705760003560e01c80638f2839701161004e5780638f2839701461015e578063cf7a1d7714610191578063d1f5789414610250578063f851a4401461030657610070565b80633659cfe61461007a5780634f1ef286146100ad5780635c60da1b1461012d575b61007861031b565b005b34801561008657600080fd5b506100786004803603602081101561009d57600080fd5b50356001600160a01b0316610335565b610078600480360360408110156100c357600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100ee57600080fd5b82018360208201111561010057600080fd5b8035906020019184600183028401116401000000008311171561012257600080fd5b50909250905061036f565b34801561013957600080fd5b5061014261041c565b604080516001600160a01b039092168252519081900360200190f35b34801561016a57600080fd5b506100786004803603602081101561018157600080fd5b50356001600160a01b0316610459565b610078600480360360608110156101a757600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156101db57600080fd5b8201836020820111156101ed57600080fd5b8035906020019184600183028401116401000000008311171561020f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610513945050505050565b6100786004803603604081101561026657600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561029157600080fd5b8201836020820111156102a357600080fd5b803590602001918460018302840111640100000000831117156102c557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610599945050505050565b34801561031257600080fd5b506101426106d9565b610323610704565b61033361032e610764565b610789565b565b61033d6107ad565b6001600160a01b0316336001600160a01b031614156103645761035f816107d2565b61036c565b61036c61031b565b50565b6103776107ad565b6001600160a01b0316336001600160a01b0316141561040f57610399836107d2565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d80600081146103f6576040519150601f19603f3d011682016040523d82523d6000602084013e6103fb565b606091505b505090508061040957600080fd5b50610417565b61041761031b565b505050565b60006104266107ad565b6001600160a01b0316336001600160a01b0316141561044e57610447610764565b9050610456565b61045661031b565b90565b6104616107ad565b6001600160a01b0316336001600160a01b03161415610364576001600160a01b0381166104bf5760405162461bcd60e51b81526004018080602001828103825260368152602001806108d76036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104e86107ad565b604080516001600160a01b03928316815291841660208301528051918290030190a161035f81610812565b600061051d610764565b6001600160a01b03161461053057600080fd5b61053a8382610599565b604080517232b4b8189c9b1b97383937bc3c9730b236b4b760691b815290519081900360130190207fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036000199091011461059057fe5b61041782610812565b60006105a3610764565b6001600160a01b0316146105b657600080fd5b604080517f656970313936372e70726f78792e696d706c656d656e746174696f6e000000008152905190819003601c0190207f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6000199091011461061657fe5b61061f82610836565b8051156106d5576000826001600160a01b0316826040518082805190602001908083835b602083106106625780518252601f199092019160209182019101610643565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d80600081146106c2576040519150601f19603f3d011682016040523d82523d6000602084013e6106c7565b606091505b505090508061041757600080fd5b5050565b60006106e36107ad565b6001600160a01b0316336001600160a01b0316141561044e576104476107ad565b61070c6107ad565b6001600160a01b0316336001600160a01b0316141561075c5760405162461bcd60e51b81526004018080602001828103825260328152602001806108a56032913960400191505060405180910390fd5b610333610333565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156107a8573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6107db81610836565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61083f8161089e565b61087a5760405162461bcd60e51b815260040180806020018281038252603b81526020018061090d603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e2066726f6d207468652070726f78792061646d696e43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a723158201a726ba5594154a0a583a3d3c32bed3fc80d1815c9b3295d1dbb8f3d240a361864736f6c63430005100032
Deployed Bytecode
0x6080604052600436106100705760003560e01c80638f2839701161004e5780638f2839701461015e578063cf7a1d7714610191578063d1f5789414610250578063f851a4401461030657610070565b80633659cfe61461007a5780634f1ef286146100ad5780635c60da1b1461012d575b61007861031b565b005b34801561008657600080fd5b506100786004803603602081101561009d57600080fd5b50356001600160a01b0316610335565b610078600480360360408110156100c357600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100ee57600080fd5b82018360208201111561010057600080fd5b8035906020019184600183028401116401000000008311171561012257600080fd5b50909250905061036f565b34801561013957600080fd5b5061014261041c565b604080516001600160a01b039092168252519081900360200190f35b34801561016a57600080fd5b506100786004803603602081101561018157600080fd5b50356001600160a01b0316610459565b610078600480360360608110156101a757600080fd5b6001600160a01b0382358116926020810135909116918101906060810160408201356401000000008111156101db57600080fd5b8201836020820111156101ed57600080fd5b8035906020019184600183028401116401000000008311171561020f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610513945050505050565b6100786004803603604081101561026657600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561029157600080fd5b8201836020820111156102a357600080fd5b803590602001918460018302840111640100000000831117156102c557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610599945050505050565b34801561031257600080fd5b506101426106d9565b610323610704565b61033361032e610764565b610789565b565b61033d6107ad565b6001600160a01b0316336001600160a01b031614156103645761035f816107d2565b61036c565b61036c61031b565b50565b6103776107ad565b6001600160a01b0316336001600160a01b0316141561040f57610399836107d2565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d80600081146103f6576040519150601f19603f3d011682016040523d82523d6000602084013e6103fb565b606091505b505090508061040957600080fd5b50610417565b61041761031b565b505050565b60006104266107ad565b6001600160a01b0316336001600160a01b0316141561044e57610447610764565b9050610456565b61045661031b565b90565b6104616107ad565b6001600160a01b0316336001600160a01b03161415610364576001600160a01b0381166104bf5760405162461bcd60e51b81526004018080602001828103825260368152602001806108d76036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104e86107ad565b604080516001600160a01b03928316815291841660208301528051918290030190a161035f81610812565b600061051d610764565b6001600160a01b03161461053057600080fd5b61053a8382610599565b604080517232b4b8189c9b1b97383937bc3c9730b236b4b760691b815290519081900360130190207fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61036000199091011461059057fe5b61041782610812565b60006105a3610764565b6001600160a01b0316146105b657600080fd5b604080517f656970313936372e70726f78792e696d706c656d656e746174696f6e000000008152905190819003601c0190207f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6000199091011461061657fe5b61061f82610836565b8051156106d5576000826001600160a01b0316826040518082805190602001908083835b602083106106625780518252601f199092019160209182019101610643565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d80600081146106c2576040519150601f19603f3d011682016040523d82523d6000602084013e6106c7565b606091505b505090508061041757600080fd5b5050565b60006106e36107ad565b6001600160a01b0316336001600160a01b0316141561044e576104476107ad565b61070c6107ad565b6001600160a01b0316336001600160a01b0316141561075c5760405162461bcd60e51b81526004018080602001828103825260328152602001806108a56032913960400191505060405180910390fd5b610333610333565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156107a8573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6107db81610836565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61083f8161089e565b61087a5760405162461bcd60e51b815260040180806020018281038252603b81526020018061090d603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b3b15159056fe43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e2066726f6d207468652070726f78792061646d696e43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a265627a7a723158201a726ba5594154a0a583a3d3c32bed3fc80d1815c9b3295d1dbb8f3d240a361864736f6c63430005100032
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.