Address Contract Partially Verified
Address
0xFecBDC398dcc8d47cb186b50D0Ae50B413919985
Balance
0 ETH
Nonce
1
Code Size
5011 bytes
Creator
0x80D1c208...4598 at tx 0xdd65adb7...00579f
Indexed Transactions
0
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