ETH Price: $2,366.38 (-5.04%)

Contract

0xa35295AeD42f2F72b88a4811372E56788b3756aF
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x490f82F5...E90c9235f
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
MultiSigNode

Compiler Version
v0.5.0+commit.1d4f565a

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2019-04-18
*/

pragma solidity >=0.5.0 <0.6.0;

/**
 * Author: Sik Jean Soon
 */

/**
 * @title SafeMath for uint256
 * @dev Math operations with safety checks that throw on error
 */
library SafeMathUint256 {
    /**
    * @dev Multiplies two numbers, throws on overflow.
    */
    function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
        if (a == 0) {
            return 0;
        }
        c = a * b;
        require(c / a == b, "Multiplier exception");
        return c;
    }

    /**
    * @dev Integer division of two numbers, truncating the quotient.
    */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b; // Solidity automatically throws when dividing by 0
    }

    /**
    * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "Subtraction exception");
        return a - b;
    }

    /**
    * @dev Adds two numbers, throws on overflow.
    */
    function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
        c = a + b;
        require(c >= a, "Addition exception");
        return c;
    }

    /**
    * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "Modulo exception");
        return a % b;
    }

}

/**
 * @title SafeMath for uint8
 * @dev Math operations with safety checks that throw on error
 */
library SafeMathUint8 {
    /**
    * @dev Multiplies two numbers, throws on overflow.
    */
    function mul(uint8 a, uint8 b) internal pure returns (uint8 c) {
        if (a == 0) {
            return 0;
        }
        c = a * b;
        require(c / a == b, "Multiplier exception");
        return c;
    }

    /**
    * @dev Integer division of two numbers, truncating the quotient.
    */
    function div(uint8 a, uint8 b) internal pure returns (uint8) {
        return a / b; // Solidity automatically throws when dividing by 0
    }

    /**
    * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint8 a, uint8 b) internal pure returns (uint8) {
        require(b <= a, "Subtraction exception");
        return a - b;
    }

    /**
    * @dev Adds two numbers, throws on overflow.
    */
    function add(uint8 a, uint8 b) internal pure returns (uint8 c) {
        c = a + b;
        require(c >= a, "Addition exception");
        return c;
    }

    /**
    * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint8 a, uint8 b) internal pure returns (uint8) {
        require(b != 0, "Modulo exception");
        return a % b;
    }

}

contract Common {
    bytes32 internal LABEL_CODE_STAKER;
    bytes32 internal LABEL_CODE_STAKER_CONTROLLER;
    bytes32 internal LABEL_CODE_SIGNER_CONTROLLER;
    bytes32 internal LABEL_CODE_SIGNER;
    bytes32 internal LABEL_CODE_BACKSYS;
    bytes32 internal LABEL_CODE_OPS;

    uint8 constant internal MAX_WALLET = 64;
    uint256 constant internal WALLET_FLAG_ALL = (2 ** (uint256(MAX_WALLET))) - 1;

    constructor() public
    {
        LABEL_CODE_STAKER = encodePacked("STAKER");
        LABEL_CODE_STAKER_CONTROLLER = encodePacked("STAKER_CONTROLLER");
        LABEL_CODE_SIGNER_CONTROLLER = encodePacked("SIGNER_CONTROLLER");
        LABEL_CODE_SIGNER = encodePacked("SIGNER");
        LABEL_CODE_BACKSYS = encodePacked("BACKSYS");
        LABEL_CODE_OPS = encodePacked("OPS");
    }

    function encodePacked(string memory s) internal pure
        returns (bytes32)
    {
        return keccak256(abi.encodePacked(s));
    }

    function convertBytesToBytes4(bytes memory _in) internal pure
        returns (bytes4 out)
    {
        if (0 == _in.length)
            return 0x0;

        assembly {
            out := mload(add(_in, 32))
        }
    }

    function isContract(address _address) internal view
        returns (bool)
    {
        uint32 size;
        assembly {
            size := extcodesize(_address)
        }
        return (0 < size);
    }

}

contract Label is Common {
    string public class;
    string public label;
    string public description;

    bytes32 public classCode;
    bytes32 public labelCode;

    constructor(string memory _class, string memory _label, string memory _description) public
    {
        class = _class;        
        label = _label;
        description = _description;

        classCode = encodePacked(_class);
        labelCode = encodePacked(_label);
    }

}


contract MultiSigNode is Label {
    using SafeMathUint8 for uint8;

    address payable public root;
    address public parent;

    // wallet index => wallet address
    mapping(uint8 => address) public wallets;
    // wallet address => wallet bit position
    mapping(address => uint8) public walletsIndex;

    // Normal wallet
    uint8 public walletCount;
    // Total wallet = normal wallet + contract wallet
    uint8 public totalWallet;

    modifier onlyRoot() {
        require(msg.sender == root, "Node.onlyRoot: Access denied");
        _;
    }

    constructor(address payable _root, address[] memory _wallets, string memory _label, string memory _description) public
        Label("NODE", _label, _description)
    {
        require(address(0) != _root, "Node: Root address is empty");
        require(MAX_WALLET >= _wallets.length, "Node: Wallet list exceeded limit");

        root = _root;

        for (uint8 i = 1; _wallets.length >= i; i = i.add(1)) {
            address wallet = _wallets[i.sub(1)];

            require(address(0) != wallet, "Node: Wallet address is empty");
            require(0 == walletsIndex[wallet], "Node: Duplicated wallet address");

            wallets[i] = wallet;
            walletsIndex[wallet] = i;

            if (!isContract(wallet))
                walletCount = walletCount.add(1);
        }

        totalWallet = uint8(_wallets.length);
    }

    function init(address _parent) external
        onlyRoot
    {
        parent = _parent;

        if (0 < totalWallet) {
            uint8 count = 0;

            for (uint8 i = 1; i <= MAX_WALLET && count <= totalWallet; i = i.add(1)) {
                address wallet = wallets[i];

                if (address(0) != wallet) {
                    count = count.add(1);

                    // Notify root this attached wallet, root will set parent address (if this is node)
                    MultiSigRoot(root).attachWalletOrNode(wallet);
                }
            }
        }
    }

    function term() external
        onlyRoot
    {
        if (0 < totalWallet) {
            uint8 count = 0;

            for (uint8 i = 1; i <= MAX_WALLET && count <= totalWallet; i = i.add(1)) {
                address wallet = wallets[i];

                if (address(0) != wallet) {
                    count = count.add(1);

                    // Notify root to remove this wallet from list
                    MultiSigRoot(root).detachWalletOrNode(wallet);
                }
            }
        }
    }

    function attach(uint8 _index, address _wallet) external
        onlyRoot
        returns (bool)
    {
        require(0 < _index && MAX_WALLET >= _index, "Node.attach: Index out of range");
        require(address(0) != _wallet, "Node.attach: Wallet address is empty");
        require(0 == walletsIndex[_wallet], "Node.attach: Duplicated wallet address");

        if (address(0) != wallets[_index])
            detach(wallets[_index]);

        walletsIndex[_wallet] = _index;
        wallets[_index] = _wallet;

        if (!isContract(_wallet))
            walletCount = walletCount.add(1);

        totalWallet = totalWallet.add(1);

        // Notify root this attached wallet, root will trigger attach operation (if this wallet is a contract)
        MultiSigRoot(root).attachWalletOrNode(_wallet);

        return true;
    }

    function detach(address _wallet) public
        onlyRoot
        returns (bool)
    {
        require(address(0) != _wallet, "Node.detach: Wallet address is empty");

        uint8 index = walletsIndex[_wallet];
        require(0 < index && MAX_WALLET >= index, "Node.detach: Wallet address is not registered");

        if (!isContract(_wallet))
            walletCount = walletCount.sub(1);

        totalWallet = totalWallet.sub(1);

        delete wallets[index];
        delete walletsIndex[_wallet];

        // Notify root to remove this wallet from list
        MultiSigRoot(root).detachWalletOrNode(_wallet);

        return true;
    }

    function getRootNode() external view
        returns (address)
    {
        if (address(0) == parent)
            return address(this);

        return MultiSigNode(parent).getRootNode();
    }

}


/**
 * NOTE: Regulator is meant for changable rules for multi-sig
 */
contract MultiSigRegulator is Label {
    using SafeMathUint8 for uint8;
    using SafeMathUint256 for uint256;

    event TransactionLimitChanged(string requirementType, uint256 limit);

    address payable public root;

    address private creator;

    // Cached parameters
    address private argTo;
    uint256 private argValue;

    bool public isSealed;

    // Daily transaction limit (mapped: requirement type => TransactionLimit)
    mapping(bytes32 => TransactionLimit) public transactionLimits;

    struct TransactionLimit {
        uint256 datetime;
        uint256 volume;
        uint256 upperLimit;
    }

    modifier onlySealed() {
        require(isSealed, "Regulator.onlySealed: Not sealed");
        _;
    }

    modifier onlyMe() {
        require(msg.sender == address(this), "Regulator.onlyMe: Access denied");
        _;
    }

    modifier onlyRoot() {
        require(msg.sender == root, "Regulator.onlyRoot: Access denied");
        _;
    }

    modifier onlyCreator() {
        require(msg.sender == creator, "Regulator.onlyCreator: Access denied");
        _;
    }

    /**
     * Supported non-payable default function
     */
    function () external
        onlyMe
        onlySealed
    {
        revert("Regulator: Not supported");
    }

    constructor(address payable _root, string memory _label, string memory _description) public
        Label("REGULATOR", _label, _description)
    {
        require(address(0) != _root, "Regulator: Root address is empty");
        root = _root;
        creator = msg.sender;
    }

    /**
     * Supported non-payable function: ERC_ER_SHI.increaseSupply
     * Only can be called by this contract itself to resolve calldata
     */
    function increaseSupply(uint256 _value, address /* _to */) external
        onlyMe
        onlySealed
    {
        defaultRequirement("increaseSupply", _value);
    }

    /**
     * Supported non-payable function: ERC_ER_SHI.decreaseSupply
     * Only can be called by this contract itself to resolve calldata
     */
    function decreaseSupply(uint256 _value, address /* _from */) external
        onlyMe
        onlySealed
    {
        defaultRequirement("decreaseSupply", _value);
    }

    /**
     * Supported non-payable function: ERC_ER_SHI.freeze
     * Only can be called by this contract itself to resolve calldata
     */
    function freeze(address /* _from */, uint256 /* _value */) external
        onlyMe
        onlySealed
    {
        requirement1Backsys();
    }

    /**
     * Supported non-payable function: ERC_ER_SHI.unfreeze
     * Only can be called by this contract itself to resolve calldata
     */
    function unfreeze(address /* _from */, uint256 /* _value */) external
        onlyMe
        onlySealed
    {
        requirement1Backsys();
    }

    /**
     * Supported non-payable function: ERC_ER_SHI.freezeAddress
     * Only can be called by this contract itself to resolve calldata
     */
    function freezeAddress(address /* _addressOf */) external
        onlyMe
        onlySealed
    {
        requirement1Backsys();
    }

    /**
     * Supported non-payable function: ERC_ER_SHI.unfreezeAddress
     * Only can be called by this contract itself to resolve calldata
     */
    function unfreezeAddress(address /* _addressOf */) external
        onlyMe
        onlySealed
    {
        requirement1Backsys();
    }

    /**
     * Supported non-payable function: Ownership.acceptOwnership
     * Only can be called by this contract itself to resolve calldata
     */
    function acceptOwnership () external
        onlyMe
        onlySealed
    {
        requirement(LABEL_CODE_OPS, 2, 1); // INDEX 2: ONE SIGNABLE
        requirement(LABEL_CODE_SIGNER_CONTROLLER, 1, 1); // INDEX 1: ONE SIGNABLE
    }

    /**
     * Supported non-payable function: Ownership.transferOwnership
     * Only can be called by this contract itself to resolve calldata
     */
    function transferOwnership (address payable /* _newOwner */) external
        onlyMe
        onlySealed
    {
        requirement(LABEL_CODE_STAKER, WALLET_FLAG_ALL, 1); // ANY ONE SIGNABLE
        requirement(LABEL_CODE_STAKER_CONTROLLER, WALLET_FLAG_ALL, uint8(-1)); // ALL SIGNABLE
        requirement(LABEL_CODE_SIGNER_CONTROLLER, WALLET_FLAG_ALL, 1); // ANY ONE SIGNABLE
    }

    /**
     * Supported non-payable function: Controllable.pause
     * Only can be called by this contract itself to resolve calldata
     */
    function pause () external
        onlyMe
        onlySealed
    {
        requirement(LABEL_CODE_STAKER_CONTROLLER, WALLET_FLAG_ALL, 1); // ANY ONE SIGNABLE
    }

    /**
     * Supported non-payable function: Controllable.resume
     * Only can be called by this contract itself to resolve calldata
     */
    function resume () external
        onlyMe
        onlySealed
    {
        requirement(LABEL_CODE_STAKER_CONTROLLER, WALLET_FLAG_ALL, 2); // ANY TWO SIGNABLE
    }

    /**
     * Supported non-payable function: MultiSigRegulator.setTransactionLimit
     */
    function setTransactionLimit(string calldata _requirementType, uint256 _limit) external
    {
        if (msg.sender == root || !isSealed) {
            // Set transaction limit
            transactionLimits[encodePacked(_requirementType)].upperLimit = _limit;
            emit TransactionLimitChanged(_requirementType, _limit);
        }
        else {
            require(msg.sender == address(this), "Regulator.setTransactionLimit: Access denied");

            // Create requirements for this transaction
            requirement(LABEL_CODE_STAKER_CONTROLLER, WALLET_FLAG_ALL, 2); // ANY TWO SIGNABLE
        }
    }

    function seal() external
        onlyCreator
    {
        require(!isSealed, "Regulator.seal: Access denied");
        isSealed = true;
    }

    function createRequirement(uint256 /* _transactionCode */, address /* _from */, address _to, uint256 _value, bytes calldata _data) external
        onlyRoot
    {
        // Cache parameters
        argTo = _to;
        argValue = _value;

        // Perform self call to determine function details for requirement setup
        (bool success, bytes memory returnData) = address(this).call.value(_value)(_data);

        if (!success) {
            // Check the error string is available or not
            if (0 == returnData.length || bytes4(0x08c379a0) != convertBytesToBytes4(returnData))
                revert("Regulator.createRequirement: Function call failed");
            else {
                bytes memory bytesArray = new bytes(returnData.length);
                for (uint256 i = 0; i < returnData.length.sub(4); i = i.add(1)) {
                    bytesArray[i] = returnData[i.add(4)];
                }

                (string memory reason) = abi.decode(bytesArray, (string));
                revert(reason);
            }
        }
    }

    function requirement(bytes32 _labelCode, uint256 _flag, uint8 _required) private
    {
        MultiSigRoot(root).createRequirement(_labelCode, _flag, _required);
    }

    function defaultRequirement(string memory _requirementType, uint256 _value) private
    {
        bytes32 t = encodePacked(_requirementType);

        // Check transaction volume limit
        TransactionLimit storage limit = transactionLimits[t];

        // Check transaction volume limit
        if (0 < limit.upperLimit) {
            // Truncate timestamp (YYYYMMDD) to daily (UTC time)
            uint256 dt = now - (now % 86400);

            if (dt == limit.datetime)
                limit.volume = limit.volume.add(_value);
            else {
                // Reset volume on new day
                limit.datetime = dt;
                limit.volume = _value;
            }

            require(limit.upperLimit >= limit.volume, "Regulator.defaultRequirement: Exceeded limit");
        }

        // Create requirement for this transaction
        requirement(LABEL_CODE_OPS, WALLET_FLAG_ALL, 4); // ANY FOUR SIGNABLE
    }

    function requirement1Backsys() private
    {
        requirement(LABEL_CODE_BACKSYS, WALLET_FLAG_ALL, 1); // ANY ONE SIGNABLE
    }

}


contract MultiSigRoot is Label {
    using SafeMathUint8 for uint8;
    using SafeMathUint256 for uint256;

    uint8 constant private WALLET_TYPE_WALLET = 1;
    uint8 constant private WALLET_TYPE_NODE = 2;

    uint8 constant private TRANSACTION_STATUS_EMPTY = 0;
    uint8 constant private TRANSACTION_STATUS_PENDING = 1;
    uint8 constant private TRANSACTION_STATUS_EXECUTED = 2;
    uint8 constant private TRANSACTION_STATUS_FAILURE = 3;
    uint8 constant private TRANSACTION_STATUS_REVOKED = 4;

    event Confirmation(address indexed sender, uint256 indexed transactionCode);
    event Revocation(address indexed sender, uint256 indexed transactionCode);
    event Submission(uint256 indexed transactionCode);
    event Requirement(uint256 indexed transactionCode, bytes32 labelCode, uint256 flag, uint8 required);
    event Execution(uint256 indexed transactionCode);
    event ExecutionFailure(uint256 indexed transactionCode);
    event Deposit(address indexed sender, uint256 value);

    event StakersChanged(address indexed stakers);
    event SignersChanged(address indexed signers);
    event RegulatorChanged(address indexed regulator);
    event StakersControllerChanged(address indexed stakersController);
    event SignersControllerChanged(address indexed signersController);
    
    event WalletOrNodeAttached(address indexed wallet);
    event WalletOrNodeDetached(address indexed wallet);
    
    address public stakers;
    address public signers;

    address public stakersController;
    address public signersController;

    address public regulator;

    // Transaction (mapped: transactionCode => Transaction)
    mapping(uint256 => Transaction) public transactions;
    uint256 public transactionCode;

    // Requirement (mapped: transactionCode + label code => requirement)
    mapping(uint256 => mapping(bytes32 => TransactionRequirement)) public requirements;
    // Prevent duplicated confirmation (mapped: transactionCode + wallet address => bool)
    mapping(uint256 => mapping(address => bool)) public confirmations;

    // Registered wallets or nodes (mapped: address => type)
    mapping(address => uint8) public registered;

    // Search node address by wallet address (mapped: wallet address => node address)
    mapping(address => address) public walletToNodes;

    // Search wallet index by wallet address (mapped: wallet address => wallet index)
    mapping(address => uint8) private walletToIndexes;

    // Search label code by wallet address (mapped: wallet address => label code)
    mapping(address => bytes32) private walletToLabelCodes;

    // Search node address by label code (mapped: label code => node address)
    mapping(bytes32 => address) private labelCodeToNodes;

    struct Transaction {
        uint8 status;
        uint8 totalRequired;

        address to;
        uint256 value;
        bytes data;
        string reason;
    }

    struct TransactionRequirement {
        uint8 required;
        uint256 flag;
    }

    modifier onlyEligible(uint256 _transactionCode) {
        require(isEligible(_transactionCode, msg.sender), "Root.onlyEligible: Not eligible");
        _;
    }

    modifier onlySignable(uint256 _transactionCode) {
        require(isSignable(_transactionCode, msg.sender), "Root.onlySignable: Not signable");
        _;
    }

    modifier onlyNode() {
        require(WALLET_TYPE_NODE == registered[msg.sender], "Root.onlyNode: Access denied");
        _;
    }

    modifier onlyWallet() {
        require(WALLET_TYPE_WALLET == registered[msg.sender], "Root.onlyWallet: Access denied");
        require(!isContract(msg.sender), "Root.onlyWallet: Is not node");
        _;
    }

    modifier onlyRegulator() {
        require(msg.sender == regulator, "Root.onlyRegulator: Access denied");
        _;
    }

    constructor(string memory _label, string memory _description) public
        Label("ROOT", _label, _description)
    {
    }

    function () external payable
    {
        if (0 < msg.value)
            emit Deposit(msg.sender, msg.value);
    }

    function isEligible(uint256 _transactionCode, address _sender) public view
        returns (bool)
    {
        uint256 flag = requirements[_transactionCode][walletToLabelCodes[_sender]].flag;

        if (0 != flag) {
            uint8 index = walletToIndexes[_sender];

            if (0 != index) {
                index = index.sub(1);

                // Check the bit is on for wallet index
                return (0 != ((flag >> index) & 1));
            }
        }
        return false;
    }

    function isSignable(uint256 _transactionCode, address _sender) public view
        returns (bool)
    {
        if (TRANSACTION_STATUS_PENDING == transactions[_transactionCode].status) {
            if (!confirmations[_transactionCode][_sender]) {
                if (0 != requirements[_transactionCode][walletToLabelCodes[_sender]].required)
                    return true;
            }
        }
        return false;
    }

    function createRequirement(bytes32 _labelCode, uint256 _flag, uint8 _required) external
        onlyRegulator
    {
        setRequirement(_labelCode, _flag, _required);
    }

    function setRequirement(bytes32 _labelCode, uint256 _flag, uint8 _required) private
    {
        require(0 < _flag, "Root.setRequirement: Confirmation flag is empty");

        uint8 totalRequired;

        // Required all wallet in the node
        if (uint8(-1) == _required) {
            address node = labelCodeToNodes[_labelCode];
            require(address(0) != node, "Root.setRequirement: Node is not found");

            totalRequired = MultiSigNode(node).walletCount();

            if (node != signers) {
                // Stakers and controllers must have at least 1 wallet attached
                require(0 < totalRequired, "Root.setRequirement: No wallet");
            }
            else {
                // Signer node allowed to be empty
                if (0 == totalRequired)
                    return;
            }

            require(0 < totalRequired, "Root.setRequirement: Confirmation required is empty");
        }
        else {
            // allowed 0 requirement, in order to support eligible user but not signable (view transaction only)
            totalRequired = _required;
        }

        require(0 == requirements[transactionCode][_labelCode].flag, "Root.setRequirement: Duplicated requirement");

        requirements[transactionCode][_labelCode] = TransactionRequirement({
            required: totalRequired,
            flag: _flag
        });

        // Increase total required in transaction
        transactions[transactionCode].totalRequired = transactions[transactionCode].totalRequired.add(totalRequired);

        emit Requirement(transactionCode, _labelCode, _flag, totalRequired);
    }

    function submit(address _to, uint256 _value, bytes calldata _data) external
        onlyWallet
        returns (uint256 /* transactionCode */) 
    {
        require(address(0) != _to, "Root.submit: Target address is empty");

        // Generate transaction id
        transactionCode = transactionCode.add(1);

        bytes4 functionId = convertBytesToBytes4(_data);

        // Create requirement that based on destination address
        if (address(this) != _to) {
            // Check this is node address or not
            if (WALLET_TYPE_NODE == registered[_to]) {
                // Calling node function
                // - 0x80882800: node.attach
                // - 0xceb6c343: node.detach
                if (bytes4(0x80882800) == functionId || bytes4(0xceb6c343) == functionId) { // node.attach or node.detach
                    address rootNode = MultiSigNode(_to).getRootNode();

                    if (rootNode == signers) {
                        // Change SIGNER need ALL SIGNER_CONTROLLER
                        setRequirement(LABEL_CODE_SIGNER_CONTROLLER, WALLET_FLAG_ALL, uint8(-1)); // ALL signable
                    }
                    else if (rootNode == signersController || rootNode == stakersController) {
                        // Change SIGNERS_CONTROLLER or STAKER_CONTROLLER need ALL STAKER
                        setRequirement(LABEL_CODE_STAKER, WALLET_FLAG_ALL, uint8(-1)); // ALL signable
                    }
                    else if (rootNode == stakers) {
                        // Change STAKER need ALL STAKER_CONTROLLER
                        setRequirement(LABEL_CODE_STAKER_CONTROLLER, WALLET_FLAG_ALL, uint8(-1)); // ALL signable
                    }
                    else {
                        revert("Root.submit: Unknown node");
                    }
                }
                else
                    revert("Root.submit: Not supported");
            }
            else {
                // Regulator create requirement
                MultiSigRegulator(regulator).createRequirement(transactionCode, msg.sender, _to, _value, _data);
            }
        }
        else {
            // Calling self functions
            // - 0xcde0a4f8: root.setRegulator
            // - 0xb47876ea: root.setSigners
            // - 0xc27dbe63: root.setStakers
            // - 0x26bc178c: root.setStakersController
            // - 0x51d996bf: root.setSignersController
            if (bytes4(0xcde0a4f8) == functionId || bytes4(0xc27dbe63) == functionId) // setRegulator or setStakers
                setRequirement(LABEL_CODE_STAKER_CONTROLLER, WALLET_FLAG_ALL, uint8(-1)); // ALL signable
            else if (bytes4(0x26bc178c) == functionId || bytes4(0x51d996bf) == functionId) // setStakersController or setSignersController
                setRequirement(LABEL_CODE_STAKER, WALLET_FLAG_ALL, uint8(-1)); // ALL signable
            else if (bytes4(0xb47876ea) == functionId) // setSigners
                setRequirement(LABEL_CODE_SIGNER_CONTROLLER, WALLET_FLAG_ALL, uint8(-1)); // ALL signable
            else
                revert("Root.submit: Not supported");
        }

        require(0 < transactions[transactionCode].totalRequired, "Root.submit: Requirement is empty");

        // Create transaction structure
        transactions[transactionCode] = Transaction({
            status: TRANSACTION_STATUS_PENDING,
            totalRequired: transactions[transactionCode].totalRequired,
            to: _to,
            value: _value,
            data: _data,
            reason: ""
        });

        emit Submission(transactionCode);

        // Confirm transaction if eligible and signable
        if (isEligible(transactionCode, msg.sender) && isSignable(transactionCode, msg.sender))
            confirmTransaction(transactionCode, transactions[transactionCode]);

        return transactionCode;
    }

    function confirm(uint256 _transactionCode) external
        onlyWallet
        onlyEligible(_transactionCode)
        onlySignable(_transactionCode)
        returns (bool)
    {
        Transaction storage transaction = transactions[_transactionCode];

        return confirmTransaction(_transactionCode, transaction);
    }

    function revoke(uint256 _transactionCode) external
        onlyWallet
        onlyEligible(_transactionCode)
        returns (bool)
    {
        require(TRANSACTION_STATUS_PENDING == transactions[_transactionCode].status, "Root.revoke: Transaction has been completed");
        transactions[_transactionCode].status = TRANSACTION_STATUS_REVOKED;

        emit Revocation(msg.sender, _transactionCode);
        return true;
    }

    function confirmTransaction(uint256 _transactionCode, Transaction storage _transaction) private
        returns (bool)
    {
        TransactionRequirement storage requirement = requirements[_transactionCode][walletToLabelCodes[msg.sender]];
        require(0 != requirement.flag && 0 != requirement.required, "Root.confirmTransaction: Requirement is empty");

        // Prevent duplicated confirmation
        require(!confirmations[_transactionCode][msg.sender], "root.confirmTransaction: Duplicated confirmation");
        confirmations[_transactionCode][msg.sender] = true;

        requirement.required = requirement.required.sub(1);
        _transaction.totalRequired = _transaction.totalRequired.sub(1);

        emit Confirmation(msg.sender, _transactionCode);

        return executeTransaction(_transactionCode, _transaction);
    }

    function executeTransaction(uint256 _transactionCode, Transaction storage _transaction) private
        returns (bool)
    {
        require(TRANSACTION_STATUS_PENDING == _transaction.status, "Root.executeTransaction: Status not active");

        if (0 == _transaction.totalRequired) {
            _transaction.status = TRANSACTION_STATUS_EXECUTED;

            // Perform remote call
            (bool success, bytes memory returnData) = _transaction.to.call.value(_transaction.value)(_transaction.data);

            if (success)
                emit Execution(_transactionCode);
            else {
                // Check the error string is available or not
                if (0 == returnData.length || bytes4(0x08c379a0) != convertBytesToBytes4(returnData))
                    _transaction.reason = "Root.executeTransaction: Function call failed";
                else {
                    bytes memory bytesArray = new bytes(returnData.length);
                    for (uint256 i = 0; i < returnData.length.sub(4); i = i.add(1)) {
                        bytesArray[i] = returnData[i.add(4)];
                    }

                    (string memory reason) = abi.decode(bytesArray, (string));
                    _transaction.reason = reason;
                }

                _transaction.status = TRANSACTION_STATUS_FAILURE;
                emit ExecutionFailure(_transactionCode);
            }

            return success;
        }

        return true;
    }

    function setRegulator(address _addressOf) external
    {
        if (address(0) != regulator)
            require(msg.sender == address(this), "Root.setRegulator: Access denied");
        
        require(MultiSigRegulator(_addressOf).isSealed(), "Root.setRegulator: Regulator is not sealed");

        regulator = setNode(regulator, _addressOf, false);
        emit RegulatorChanged(regulator);
    }

    function setStakers(address _addressOf) external
    {
        if (address(0) != stakers)
            require(msg.sender == address(this), "Root.setStakers: Access denied");

        if (isContract(_addressOf))
            require(0 < MultiSigNode(_addressOf).walletCount(), "Root.setStakers: No wallet");

        stakers = setNode(stakers, _addressOf, true);
        emit StakersChanged(stakers);
    }

    function setSigners(address _addressOf) external
        returns (bool)
    {
        if (address(0) != signers)
            require(msg.sender == address(this), "Root.setSigners: Access denied");

        // Signer node allowed to be empty

        signers = setNode(signers, _addressOf, true);
        emit SignersChanged(signers);
        return true;
    }

    function setStakersController(address _addressOf) external
    {
        if (address(0) != stakersController)
            require(msg.sender == address(this), "Root.setStakersController: Access denied");

        if (isContract(_addressOf))
            require(0 < MultiSigNode(_addressOf).walletCount(), "Root.setStakersController: No wallet");

        stakersController = setNode(stakersController, _addressOf, true);
        emit StakersControllerChanged(stakersController);
    }

    function setSignersController(address _addressOf) external
    {
        if (address(0) != signersController)
            require(msg.sender == address(this), "Root.setSignersController: Access denied");

        if (isContract(_addressOf))
            require(0 < MultiSigNode(_addressOf).walletCount(), "Root.setSignersController: No wallet");

        signersController = setNode(signersController, _addressOf, true);
        emit SignersControllerChanged(signersController);
    }

    function setNode(address _from, address _to, bool needAttachment) private
        returns (address)
    {
        require(address(0) != _to, "Root.setNode: Address is empty");

        if (needAttachment) {
            require(0 == registered[_to], "Root.setNode: Duplicated node");

            // Remove node from list
            if (address(0) != _from) {
                if (isContract(_from)) {
                    // detach node
                    MultiSigNode(_from).term();
                }

                delete registered[_from];
            }

            if (isContract(_to)) {
                // Mark address as registered node
                registered[_to] = WALLET_TYPE_NODE;

                if (needAttachment) {
                    // Attach node (parrent address = 0x0)
                    MultiSigNode(_to).init(address(0));
                }
            }
            else {
                // Mark address as registered wallet
                registered[_to] = WALLET_TYPE_WALLET;
            }
        }

        return _to;
    }

    function attachWalletOrNode(address _wallet) external
        onlyNode
        returns (bool)
    {
        require(address(0) != _wallet, "Root.attachWalletOrNode: Wallet address is empty");
        require(0 == registered[_wallet], "Root.attachWalletOrNode: Duplicated wallet address");

        bytes32 labelCode = MultiSigNode(msg.sender).labelCode();

        walletToNodes[_wallet] = msg.sender;
        walletToIndexes[_wallet] = MultiSigNode(msg.sender).walletsIndex(_wallet);
        walletToLabelCodes[_wallet] = labelCode;

        labelCodeToNodes[labelCode] = msg.sender;

        if (isContract(_wallet)) {
            // Mark address as registered node
            registered[_wallet] = WALLET_TYPE_NODE;

            // Attach node with their parent address
            MultiSigNode(_wallet).init(msg.sender);
        }
        else {
            // Mark address as registered wallet
            registered[_wallet] = WALLET_TYPE_WALLET;
        }

        emit WalletOrNodeAttached(_wallet);

        return true;
    }

    function detachWalletOrNode(address _wallet) external
        onlyNode
        returns (bool)
    {
        require(address(0) != _wallet, "Root.detachWalletOrNode: Wallet address is empty");
        require(0 != registered[_wallet], "Root.detachWalletOrNode: Wallet address is not registered");

        if (isContract(_wallet)) {
            // Detach node with their parent
            MultiSigNode(_wallet).term();

            bytes32 labelCode = MultiSigNode(msg.sender).labelCode();

            delete labelCodeToNodes[labelCode];
        }

        delete registered[_wallet];
        delete walletToNodes[_wallet];
        delete walletToIndexes[_wallet];
        delete walletToLabelCodes[_wallet];

        emit WalletOrNodeDetached(_wallet);

        return true;
    }

}

Contract Security Audit

Contract ABI

API
[{"constant":false,"inputs":[{"name":"_parent","type":"address"}],"name":"init","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"walletCount","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getRootNode","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"parent","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"description","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint8"}],"name":"wallets","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_index","type":"uint8"},{"name":"_wallet","type":"address"}],"name":"attach","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalWallet","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"term","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"class","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"labelCode","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"walletsIndex","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"label","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"}],"name":"detach","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"classCode","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"root","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_root","type":"address"},{"name":"_wallets","type":"address[]"},{"name":"_label","type":"string"},{"name":"_description","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]

Deployed Bytecode

0x6080604052600436106100e6576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806319ab453c146100eb57806329b57c691461013c57806338d1fcc31461016d57806360f96a8f146101c45780637284e4161461021b578063733f28a8146102ab57806380882800146103295780638628993f1461039f578063a10ffbed146103d0578063bff852fa146103e7578063c47d1a7a14610477578063c79e6429146104a2578063cb4774c41461050d578063ceb6c3431461059d578063e24ff74414610606578063ebf0c71714610631575b600080fd5b3480156100f757600080fd5b5061013a6004803603602081101561010e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610688565b005b34801561014857600080fd5b50610151610992565b604051808260ff1660ff16815260200191505060405180910390f35b34801561017957600080fd5b506101826109a5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101d057600080fd5b506101d9610acb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561022757600080fd5b50610230610af1565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610270578082015181840152602081019050610255565b50505050905090810190601f16801561029d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102b757600080fd5b506102e7600480360360208110156102ce57600080fd5b81019080803560ff169060200190929190505050610b8f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561033557600080fd5b506103856004803603604081101561034c57600080fd5b81019080803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bc2565b604051808215151515815260200191505060405180910390f35b3480156103ab57600080fd5b506103b46111c5565b604051808260ff1660ff16815260200191505060405180910390f35b3480156103dc57600080fd5b506103e56111d8565b005b3480156103f357600080fd5b506103fc6114a0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561043c578082015181840152602081019050610421565b50505050905090810190601f1680156104695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561048357600080fd5b5061048c61153e565b6040518082815260200191505060405180910390f35b3480156104ae57600080fd5b506104f1600480360360208110156104c557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611544565b604051808260ff1660ff16815260200191505060405180910390f35b34801561051957600080fd5b50610522611564565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610562578082015181840152602081019050610547565b50505050905090810190601f16801561058f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156105a957600080fd5b506105ec600480360360208110156105c057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611602565b604051808215151515815260200191505060405180910390f35b34801561061257600080fd5b5061061b611ab7565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b50610646611abd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561074d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f64652e6f6e6c79526f6f743a204163636573732064656e6965640000000081525060200191505060405180910390fd5b80600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600f60019054906101000a900460ff1660ff166000101561098f5760008090506000600190505b604060ff168160ff16111580156107e15750600f60019054906101000a900460ff1660ff168260ff1611155b1561098c576000600d60008360ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff1614151561096d5761087160018460ff16611ae390919063ffffffff16565b9250600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c4def70a826040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561093057600080fd5b505af1158015610944573d6000803e3d6000fd5b505050506040513d602081101561095a57600080fd5b8101908080519060200190929190505050505b5061098560018260ff16611ae390919063ffffffff16565b90506107b5565b50505b50565b600f60009054906101000a900460ff1681565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff161415610a0657309050610ac8565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338d1fcc36040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b158015610a8a57600080fd5b505afa158015610a9e573d6000803e3d6000fd5b505050506040513d6020811015610ab457600080fd5b810190808051906020019092919050505090505b90565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60088054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b875780601f10610b5c57610100808354040283529160200191610b87565b820191906000526020600020905b815481529060010190602001808311610b6a57829003601f168201915b505050505081565b600d6020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610c89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f64652e6f6e6c79526f6f743a204163636573732064656e6965640000000081525060200191505060405180910390fd5b8260ff166000108015610ca357508260ff16604060ff1610155b1515610d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4e6f64652e6174746163683a20496e646578206f7574206f662072616e67650081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff1614151515610de2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f4e6f64652e6174746163683a2057616c6c65742061646472657373206973206581526020017f6d7074790000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600e60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1660ff166000141515610ecf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001807f4e6f64652e6174746163683a204475706c6963617465642077616c6c6574206181526020017f646472657373000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600d60008460ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff16141515610f8257610f80600d60008560ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611602565b505b82600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908360ff16021790555081600d60008560ff1660ff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061103b82611b71565b1515611082576110676001600f60009054906101000a900460ff1660ff16611ae390919063ffffffff16565b600f60006101000a81548160ff021916908360ff1602179055505b6110a86001600f60019054906101000a900460ff1660ff16611ae390919063ffffffff16565b600f60016101000a81548160ff021916908360ff160217905550600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c4def70a836040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561117f57600080fd5b505af1158015611193573d6000803e3d6000fd5b505050506040513d60208110156111a957600080fd5b8101908080519060200190929190505050506001905092915050565b600f60019054906101000a900460ff1681565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561129d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f64652e6f6e6c79526f6f743a204163636573732064656e6965640000000081525060200191505060405180910390fd5b600f60019054906101000a900460ff1660ff166000101561149e5760008090506000600190505b604060ff168160ff16111580156112f05750600f60019054906101000a900460ff1660ff168260ff1611155b1561149b576000600d60008360ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff1614151561147c5761138060018460ff16611ae390919063ffffffff16565b9250600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d4ab68e4826040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b15801561143f57600080fd5b505af1158015611453573d6000803e3d6000fd5b505050506040513d602081101561146957600080fd5b8101908080519060200190929190505050505b5061149460018260ff16611ae390919063ffffffff16565b90506112c4565b50505b565b60068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156115365780601f1061150b57610100808354040283529160200191611536565b820191906000526020600020905b81548152906001019060200180831161151957829003601f168201915b505050505081565b600a5481565b600e6020528060005260406000206000915054906101000a900460ff1681565b60078054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156115fa5780601f106115cf576101008083540402835291602001916115fa565b820191906000526020600020905b8154815290600101906020018083116115dd57829003601f168201915b505050505081565b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156116c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f64652e6f6e6c79526f6f743a204163636573732064656e6965640000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff1614151515611794576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001807f4e6f64652e6465746163683a2057616c6c65742061646472657373206973206581526020017f6d7074790000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6000600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1690508060ff1660001080156117ff57508060ff16604060ff1610155b1515611899576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001807f4e6f64652e6465746163683a2057616c6c65742061646472657373206973206e81526020017f6f7420726567697374657265640000000000000000000000000000000000000081525060400191505060405180910390fd5b6118a283611b71565b15156118e9576118ce6001600f60009054906101000a900460ff1660ff16611b8a90919063ffffffff16565b600f60006101000a81548160ff021916908360ff1602179055505b61190f6001600f60019054906101000a900460ff1660ff16611b8a90919063ffffffff16565b600f60016101000a81548160ff021916908360ff160217905550600d60008260ff1660ff16815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81549060ff0219169055600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d4ab68e4846040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050602060405180830381600087803b158015611a7157600080fd5b505af1158015611a85573d6000803e3d6000fd5b505050506040513d6020811015611a9b57600080fd5b8101908080519060200190929190505050506001915050919050565b60095481565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081830190508260ff168160ff1610151515611b68576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4164646974696f6e20657863657074696f6e000000000000000000000000000081525060200191505060405180910390fd5b80905092915050565b600080823b90508063ffffffff16600010915050919050565b60008260ff168260ff1611151515611c0a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f5375627472616374696f6e20657863657074696f6e000000000000000000000081525060200191505060405180910390fd5b81830390509291505056fea165627a7a723058204aea8e7ad23668107a3b2b5be25f4a6fe69e1bd29b74cc8affbbbe701b6a48680029

Swarm Source

bzzr://4aea8e7ad23668107a3b2b5be25f4a6fe69e1bd29b74cc8affbbbe701b6a4868

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.