Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xFecBDC398dcc8d47cb186b50D0Ae50B413919985
Balance 0 ETH
Nonce 1
Code Size 5011 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

5011 bytes
0x608060405260043610610083576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301173672146100fa5780631398a5f6146101af57806385b2566a146101da578063a0e67e2b1461026f578063b7d5e564146102db578063c6a2a9f114610388578063d74f8edd146103b3575b60003411156100f8577f5af8184bef8e4b45eb9f6ed7734d04da38ced226495548f46e0c8ff8d7d9a5243334604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b005b34801561010657600080fd5b506101ad600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019082018035906020019190919293919293908035906020019082018035906020019190919293919293908035906020019082018035906020019190919293919293905050506103de565b005b3480156101bb57600080fd5b506101c461077a565b6040518082815260200191505060405180910390f35b3480156101e657600080fd5b5061026d600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050610784565b005b34801561027b57600080fd5b50610284610a9b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102c75780820151818401526020810190506102ac565b505050509050019250505060405180910390f35b3480156102e757600080fd5b50610386600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050610b29565b005b34801561039457600080fd5b5061039d610da4565b6040518082815260200191505060405180910390f35b3480156103bf57600080fd5b506103c8610dae565b6040518082815260200191505060405180910390f35b3073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614151515610482576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e6f7420616c6c6f772073656e64696e6720746f20796f757273656c6600000081525060200191505060405180910390fd5b6000871115156104fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4572633230207370656e642076616c756520696e76616c69640000000000000081525060200191505060405180910390fd5b610595888a89898980806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050888880806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050878780806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050610db3565b1515610609576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f696e76616c6964207369676e617475726573000000000000000000000000000081525060200191505060405180910390fd5b6001600354016003819055508773ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a896040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b1580156106b857600080fd5b505af11580156106cc573d6000803e3d6000fd5b505050507f3d1915a2cdcecdfffc5eb2a7994c069bad5d4aa96aca85667dedbe60bb80491c888a89604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a1505050505050505050565b6000600254905090565b3073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614151515610828576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e6f7420616c6c6f772073656e64696e6720746f20796f757273656c6600000081525060200191505060405180910390fd5b863073ffffffffffffffffffffffffffffffffffffffff16311015801561084f5750600087115b15156108c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f62616c616e6365206f72207370656e642076616c756520696e76616c6964000081525060200191505060405180910390fd5b61095f60008989898980806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050888880806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050878780806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050610db3565b15156109d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f696e76616c6964207369676e617475726573000000000000000000000000000081525060200191505060405180910390fd5b6001600354016003819055508773ffffffffffffffffffffffffffffffffffffffff166108fc889081150290604051600060405180830381858888f19350505050158015610a25573d6000803e3d6000fd5b507fd3eec71143c45f28685b24760ea218d476917aa0ac0392a55e5304cef40bd2b68888604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15050505050505050565b60606001805480602002602001604051908101604052809291908181526020018280548015610b1f57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610ad5575b5050505050905090565b3073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff1614151515610bcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e6f7420616c6c6f772073656e64696e6720746f20796f757273656c6600000081525060200191505060405180910390fd5b610c6960098b8b8b8b808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050508a8a80806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050898980806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050610db3565b1515610cdd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f696e76616c6964207369676e617475726573000000000000000000000000000081525060200191505060405180910390fd5b6001600354016003819055508973ffffffffffffffffffffffffffffffffffffffff168983836040518083838082843782019150509250505060006040518083038185875af19250505015610d98577f62ee6f1a2424e70e5cff9d61a0d928aa101e198f192d726c651f1bdad1cd40d98a8a604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b50505050505050505050565b6000600354905090565b600981565b6000806060600085518751141515610dca57600080fd5b84518651141515610dda57600080fd5b600180549050875111151515610def57600080fd5b600254875110151515610e0157600080fd5b610e0c8a8a8a610f94565b92508651604051908082528060200260200182016040528015610e3e5781602001602082028038833980820191505090505b509150600090505b8651811015610f6f57600183601b8984815181101515610e6257fe5b90602001906020020151018884815181101515610e7b57fe5b906020019060200201518885815181101515610e9357fe5b90602001906020020151604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015610f0e573d6000803e3d6000fd5b505050602060405103518282815181101515610f2657fe5b9060200190602002019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610e46565b610f78826110c8565b1515610f8357600080fd5b600193505050509695505050505050565b6000806060610fa4868686611202565b91506040805190810160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250905080826040516020018083805190602001908083835b6020831015156110185780518252602082019150602081019050602083039250610ff3565b6001836020036101000a0380198251168184511680821785525050505050509050018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b602083101515611090578051825260208201915060208101905060208303925061106b565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020925050509392505050565b6000806000600180549050845111156110e457600092506111fb565b600091505b83518210156111f657600080858481518110151561110357fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151561116457600092506111fb565b600090505b818110156111e957838181518110151561117f57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1684838151811015156111ad57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1614156111dc57600092506111fb565b8080600101915050611169565b81806001019250506110e9565b600192505b5050919050565b60008030858585600354604051602001808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c01000000000000000000000000028152601401838152602001828152602001955050505050506040516020818303038152906040526040518082805190602001908083835b60208310151561132d5780518252602082019150602081019050602083039250611308565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902090508091505093925050505600a165627a7a7230582078b9bd2ebc8e0cff6a86028165c6917f9c74aace4df5f27fa2001ad2db0e533d0029

Verified Source Code Partial Match

Compiler: v0.4.26+commit.4563c3fc EVM: byzantium Optimization: No
OwnbitMultiSig.sol 192 lines
pragma solidity ^0.4.26;

// This is the ETH/ERC20 multisig contract for Ownbit.
//
// For 2-of-3 multisig, to authorize a spend, two signtures must be provided by 2 of the 3 owners.
// To generate the message to be signed, provide the destination address and
// spend amount (in wei) to the generateMessageToSign method.
// The signatures must be provided as the (v, r, s) hex-encoded coordinates.
// The S coordinate must be 0x00 or 0x01 corresponding to 0x1b and 0x1c, respectively.
//
// WARNING: The generated message is only valid until the next spend is executed.
//          after that, a new message will need to be calculated.
//
//
// INFO: This contract is ERC20 compatible.
// This contract can both receive ETH and ERC20 tokens.
// Notice that NFT (ERC721/ERC1155) is not supported.

interface Erc20 {
  function approve(address, uint256) public;

  function transfer(address, uint256) public;
    
  //function balanceOf(address) view public returns (uint256);
}

contract OwnbitMultiSig {
    
  uint constant public MAX_OWNER_COUNT = 9;

  // The N addresses which control the funds in this contract. The
  // owners of M of these addresses will need to both sign a message
  // allowing the funds in this contract to be spent.
  mapping(address => bool) private isOwner;
  address[] private owners;
  uint private required;

  // The contract nonce is not accessible to the contract so we
  // implement a nonce-like variable for replay protection.
  uint256 private spendNonce = 0;
  
  // An event sent when funds are received.
  event Funded(address from, uint value);
  
  // An event sent when a spend is triggered to the given address.
  event Spent(address to, uint transfer);
  
  // An event sent when a spendERC20 is triggered to the given address.
  event SpentERC20(address erc20contract, address to, uint transfer);
  
  // An event sent when an spendAny is executed.
  event SpentAny(address to, uint transfer);

  modifier validRequirement(uint ownerCount, uint _required) {
    require (ownerCount <= MAX_OWNER_COUNT
            && _required <= ownerCount
            && _required >= 1);
    _;
  }
  
  /// @dev Contract constructor sets initial owners and required number of confirmations.
  /// @param _owners List of initial owners.
  /// @param _required Number of required confirmations.
  constructor(address[] _owners, uint _required) public validRequirement(_owners.length, _required) {
    for (uint i = 0; i < _owners.length; i++) {
        //onwer should be distinct, and non-zero
        if (isOwner[_owners[i]] || _owners[i] == address(0x0)) {
            revert();
        }
        isOwner[_owners[i]] = true;
    }
    owners = _owners;
    required = _required;
  }


  // The fallback function for this contract.
  function() public payable {
    if (msg.value > 0) {
        emit Funded(msg.sender, msg.value);
    }
  }
  
  // @dev Returns list of owners.
  // @return List of owner addresses.
  function getOwners() public view returns (address[]) {
    return owners;
  }
    
  function getSpendNonce() public view returns (uint256) {
    return spendNonce;
  }
    
  function getRequired() public view returns (uint) {
    return required;
  }

  // Generates the message to sign given the output destination address and amount.
  // includes this contract's address and a nonce for replay protection.
  // One option to independently verify: https://leventozturk.com/engineering/sha3/ and select keccak
  function generateMessageToSign(address erc20Contract, address destination, uint256 value) private view returns (bytes32) {
    //the sequence should match generateMultiSigV2 in JS
    bytes32 message = keccak256(abi.encodePacked(address(this), erc20Contract, destination, value, spendNonce));
    return message;
  }
  
  function _messageToRecover(address erc20Contract, address destination, uint256 value) private view returns (bytes32) {
    bytes32 hashedUnsignedMessage = generateMessageToSign(erc20Contract, destination, value);
    bytes memory prefix = "\x19Ethereum Signed Message:\n32";
    return keccak256(abi.encodePacked(prefix, hashedUnsignedMessage));
  }
  
  // @destination: the ether receiver address.
  // @value: the ether value, in wei.
  // @vs, rs, ss: the signatures
  function spend(address destination, uint256 value, uint8[] vs, bytes32[] rs, bytes32[] ss) external {
    require(destination != address(this), "Not allow sending to yourself");
    require(address(this).balance >= value && value > 0, "balance or spend value invalid");
    require(_validSignature(address(0x0), destination, value, vs, rs, ss), "invalid signatures");
    spendNonce = spendNonce + 1;
    //transfer will throw if fails
    destination.transfer(value);
    emit Spent(destination, value);
  }
  
  // @erc20contract: the erc20 contract address.
  // @destination: the token receiver address.
  // @value: the token value, in token minimum unit.
  // @vs, rs, ss: the signatures
  function spendERC20(address destination, address erc20contract, uint256 value, uint8[] vs, bytes32[] rs, bytes32[] ss) external {
    require(destination != address(this), "Not allow sending to yourself");
    //transfer erc20 token
    //uint256 tokenValue = Erc20(erc20contract).balanceOf(address(this));
    require(value > 0, "Erc20 spend value invalid");
    require(_validSignature(erc20contract, destination, value, vs, rs, ss), "invalid signatures");
    spendNonce = spendNonce + 1;
    // transfer tokens from this contract to the destination address
    Erc20(erc20contract).transfer(destination, value);
    emit SpentERC20(erc20contract, destination, value);
  }
  
  //0x9 is used for spendAny
  //be careful with any action, data is not included into signature computation. So any data can be included in spendAny.
  //This is usually for some emergent recovery, for example, recovery of NTFs, etc.
  //Owners should not generate 0x9 based signatures in normal cases.
  function spendAny(address destination, uint256 value, uint8[] vs, bytes32[] rs, bytes32[] ss, bytes data) external {
    require(destination != address(this), "Not allow sending to yourself");
    require(_validSignature(address(0x9), destination, value, vs, rs, ss), "invalid signatures");
    spendNonce = spendNonce + 1;
    //transfer tokens from this contract to the destination address
    if (destination.call.value(value)(data)) {
        emit SpentAny(destination, value);
    }
  }

  // Confirm that the signature triplets (v1, r1, s1) (v2, r2, s2) ...
  // authorize a spend of this contract's funds to the given destination address.
  function _validSignature(address erc20Contract, address destination, uint256 value, uint8[] vs, bytes32[] rs, bytes32[] ss) private view returns (bool) {
    require(vs.length == rs.length);
    require(rs.length == ss.length);
    require(vs.length <= owners.length);
    require(vs.length >= required);
    bytes32 message = _messageToRecover(erc20Contract, destination, value);
    address[] memory addrs = new address[](vs.length);
    for (uint i = 0; i < vs.length; i++) {
        //recover the address associated with the public key from elliptic curve signature or return zero on error 
        addrs[i] = ecrecover(message, vs[i]+27, rs[i], ss[i]);
    }
    require(_distinctOwners(addrs));
    return true;
  }
  
  // Confirm the addresses as distinct owners of this contract.
  function _distinctOwners(address[] addrs) private view returns (bool) {
    if (addrs.length > owners.length) {
        return false;
    }
    for (uint i = 0; i < addrs.length; i++) {
        if (!isOwner[addrs[i]]) {
            return false;
        }
        //address should be distinct
        for (uint j = 0; j < i; j++) {
            if (addrs[i] == addrs[j]) {
                return false;
            }
        }
    }
    return true;
  }
  
}

Read Contract

MAX_OWNER_COUNT 0xd74f8edd → uint256
getOwners 0xa0e67e2b → address[]
getRequired 0x1398a5f6 → uint256
getSpendNonce 0xc6a2a9f1 → uint256

Write Contract 3 functions

These functions modify contract state and require a wallet transaction to execute.

spend 0x85b2566a
address destination
uint256 value
uint8[] vs
bytes32[] rs
bytes32[] ss
spendAny 0xb7d5e564
address destination
uint256 value
uint8[] vs
bytes32[] rs
bytes32[] ss
bytes data
spendERC20 0x01173672
address destination
address erc20contract
uint256 value
uint8[] vs
bytes32[] rs
bytes32[] ss

Recent Transactions

No transactions found for this address