new instancing structure and folder organization
This commit is contained in:
parent
0decba680f
commit
13efef9869
|
@ -1,14 +0,0 @@
|
||||||
pragma solidity ^0.4.15;
|
|
||||||
|
|
||||||
import "./MultiSigStub.sol";
|
|
||||||
|
|
||||||
contract MultiSigFactory {
|
|
||||||
|
|
||||||
event Create(address indexed caller, address createdContract);
|
|
||||||
|
|
||||||
function create(address[] owners, uint256 required) returns (address wallet) {
|
|
||||||
wallet = new MultiSigStub(owners, required);
|
|
||||||
Create(msg.sender, wallet);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,232 +0,0 @@
|
||||||
pragma solidity ^0.4.15;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @title MultiSigStub
|
|
||||||
* Contract that delegates calls to a library to build a full MultiSigWallet that is cheap to create.
|
|
||||||
*/
|
|
||||||
contract MultiSigStub {
|
|
||||||
|
|
||||||
address[] public owners;
|
|
||||||
address[] public tokens;
|
|
||||||
mapping (uint => Transaction) public transactions;
|
|
||||||
mapping (uint => mapping (address => bool)) public confirmations;
|
|
||||||
uint public transactionCount;
|
|
||||||
|
|
||||||
struct Transaction {
|
|
||||||
address destination;
|
|
||||||
uint value;
|
|
||||||
bytes data;
|
|
||||||
bool executed;
|
|
||||||
}
|
|
||||||
|
|
||||||
function MultiSigStub(address[] _owners, uint256 _required) {
|
|
||||||
//bytes4 sig = bytes4(sha3("constructor(address[],uint256)"));
|
|
||||||
bytes4 sig = 0x36756a23;
|
|
||||||
uint argarraysize = (2 + _owners.length);
|
|
||||||
uint argsize = (1 + argarraysize) * 32;
|
|
||||||
uint size = 4 + argsize;
|
|
||||||
bytes32 mData = _malloc(size);
|
|
||||||
|
|
||||||
assembly {
|
|
||||||
mstore(mData, sig)
|
|
||||||
codecopy(add(mData, 0x4), sub(codesize, argsize), argsize)
|
|
||||||
}
|
|
||||||
_delegatecall(mData, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
modifier delegated {
|
|
||||||
uint size = msg.data.length;
|
|
||||||
bytes32 mData = _malloc(size);
|
|
||||||
|
|
||||||
assembly {
|
|
||||||
calldatacopy(mData, 0x0, size)
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes32 mResult = _delegatecall(mData, size);
|
|
||||||
_;
|
|
||||||
assembly {
|
|
||||||
return(mResult, 0x20)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function()
|
|
||||||
payable
|
|
||||||
delegated
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitTransaction(address destination, uint value, bytes data)
|
|
||||||
public
|
|
||||||
delegated
|
|
||||||
returns (uint)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function confirmTransaction(uint transactionId)
|
|
||||||
public
|
|
||||||
delegated
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function watch(address _tokenAddr)
|
|
||||||
public
|
|
||||||
delegated
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMyTokenList(address[] _tokenList)
|
|
||||||
public
|
|
||||||
delegated
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @dev Returns the confirmation status of a transaction.
|
|
||||||
/// @param transactionId Transaction ID.
|
|
||||||
/// @return Confirmation status.
|
|
||||||
function isConfirmed(uint transactionId)
|
|
||||||
public
|
|
||||||
constant
|
|
||||||
delegated
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Web3 call functions
|
|
||||||
*/
|
|
||||||
function tokenBalances(address tokenAddress)
|
|
||||||
public
|
|
||||||
constant
|
|
||||||
delegated
|
|
||||||
returns (uint)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @dev Returns number of confirmations of a transaction.
|
|
||||||
/// @param transactionId Transaction ID.
|
|
||||||
/// @return Number of confirmations.
|
|
||||||
function getConfirmationCount(uint transactionId)
|
|
||||||
public
|
|
||||||
constant
|
|
||||||
delegated
|
|
||||||
returns (uint)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Returns total number of transactions after filters are applied.
|
|
||||||
/// @param pending Include pending transactions.
|
|
||||||
/// @param executed Include executed transactions.
|
|
||||||
/// @return Total number of transactions after filters are applied.
|
|
||||||
function getTransactionCount(bool pending, bool executed)
|
|
||||||
public
|
|
||||||
constant
|
|
||||||
delegated
|
|
||||||
returns (uint)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Returns list of owners.
|
|
||||||
/// @return List of owner addresses.
|
|
||||||
function getOwners()
|
|
||||||
public
|
|
||||||
constant
|
|
||||||
returns (address[])
|
|
||||||
{
|
|
||||||
return owners;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Returns list of tokens.
|
|
||||||
/// @return List of token addresses.
|
|
||||||
function getTokenList()
|
|
||||||
public
|
|
||||||
constant
|
|
||||||
returns (address[])
|
|
||||||
{
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Returns array with owner addresses, which confirmed transaction.
|
|
||||||
/// @param transactionId Transaction ID.
|
|
||||||
/// @return Returns array of owner addresses.
|
|
||||||
function getConfirmations(uint transactionId)
|
|
||||||
public
|
|
||||||
constant
|
|
||||||
returns (address[] _confirmations)
|
|
||||||
{
|
|
||||||
address[] memory confirmationsTemp = new address[](owners.length);
|
|
||||||
uint count = 0;
|
|
||||||
uint i;
|
|
||||||
for (i = 0; i < owners.length; i++) {
|
|
||||||
if (confirmations[transactionId][owners[i]]) {
|
|
||||||
confirmationsTemp[count] = owners[i];
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_confirmations = new address[](count);
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
_confirmations[i] = confirmationsTemp[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Returns list of transaction IDs in defined range.
|
|
||||||
/// @param from Index start position of transaction array.
|
|
||||||
/// @param to Index end position of transaction array.
|
|
||||||
/// @param pending Include pending transactions.
|
|
||||||
/// @param executed Include executed transactions.
|
|
||||||
/// @return Returns array of transaction IDs.
|
|
||||||
function getTransactionIds(uint from, uint to, bool pending, bool executed)
|
|
||||||
public
|
|
||||||
constant
|
|
||||||
returns (uint[] _transactionIds)
|
|
||||||
{
|
|
||||||
uint[] memory transactionIdsTemp = new uint[](transactionCount);
|
|
||||||
uint count = 0;
|
|
||||||
uint i;
|
|
||||||
for (i = 0; i < transactionCount; i++) {
|
|
||||||
if (pending && !transactions[i].executed || executed && transactions[i].executed) {
|
|
||||||
transactionIdsTemp[count] = i;
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_transactionIds = new uint[](to - from);
|
|
||||||
for (i = from; i < to; i++) {
|
|
||||||
_transactionIds[i - from] = transactionIdsTemp[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function _malloc(uint size)
|
|
||||||
private
|
|
||||||
returns(bytes32 mData)
|
|
||||||
{
|
|
||||||
assembly {
|
|
||||||
mData := mload(0x40)
|
|
||||||
mstore(0x40, add(mData, size))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function _delegatecall(bytes32 mData, uint size)
|
|
||||||
private
|
|
||||||
returns(bytes32 mResult)
|
|
||||||
{
|
|
||||||
address target = 0xc0FFeEE61948d8993864a73a099c0E38D887d3F4; //Multinetwork
|
|
||||||
mResult = _malloc(32);
|
|
||||||
bool failed;
|
|
||||||
|
|
||||||
assembly {
|
|
||||||
failed := iszero(delegatecall(sub(gas, 10000), target, mData, size, mResult, 0x20))
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!failed);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
pragma solidity ^0.4.8;
|
||||||
|
|
||||||
|
contract Controlled {
|
||||||
|
/// @notice The address of the controller is the only address that can call
|
||||||
|
/// a function with this modifier
|
||||||
|
modifier onlyController {
|
||||||
|
require(msg.sender == controller);
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
address public controller;
|
||||||
|
|
||||||
|
function Controlled() public {
|
||||||
|
controller = msg.sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Changes the controller of the contract
|
||||||
|
/// @param _newController The new controller of the contract
|
||||||
|
function changeController(address _newController) public onlyController {
|
||||||
|
controller = _newController;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
pragma solidity ^0.4.17;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title DelegatedCall
|
||||||
|
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||||
|
* @dev Abstract contract that delegates calls by `delegated` modifier to result of `targetDelegatedCall()`
|
||||||
|
* Important to avoid overwriting wrong storage pointers is that never define storage to this contract
|
||||||
|
*/
|
||||||
|
contract DelegatedCall {
|
||||||
|
/**
|
||||||
|
* @dev delegates the call of this function
|
||||||
|
*/
|
||||||
|
modifier delegated {
|
||||||
|
//require successfull delegate call to remote `_target()`
|
||||||
|
require(targetDelegatedCall().delegatecall(msg.data));
|
||||||
|
assembly {
|
||||||
|
let outSize := returndatasize
|
||||||
|
let outDataPtr := mload(0x40) //load memory
|
||||||
|
returndatacopy(outDataPtr, 0, outSize) //copy last return into pointer
|
||||||
|
return(outDataPtr, outSize)
|
||||||
|
}
|
||||||
|
assert(false); //should never reach here
|
||||||
|
_; //never will execute local logic
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev defines the address for delegation of calls
|
||||||
|
*/
|
||||||
|
function targetDelegatedCall()
|
||||||
|
internal
|
||||||
|
constant
|
||||||
|
returns(address);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
pragma solidity ^0.4.17;
|
||||||
|
|
||||||
|
import "../common/Controlled.sol";
|
||||||
|
|
||||||
|
contract Factory is Controlled {
|
||||||
|
|
||||||
|
event NewKernel(address newKernel, bytes infohash);
|
||||||
|
|
||||||
|
struct Version {
|
||||||
|
uint256 blockNumber;
|
||||||
|
uint256 timestamp;
|
||||||
|
address kernel;
|
||||||
|
bytes infohash;
|
||||||
|
}
|
||||||
|
mapping (address => uint256) versionMap;
|
||||||
|
|
||||||
|
Version[] versionLog;
|
||||||
|
uint256 latestUpdate;
|
||||||
|
address latestKernel;
|
||||||
|
|
||||||
|
function Factory(address _kernel, bytes _infohash)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
_setKernel(_kernel, _infohash);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setKernel(address _kernel, bytes _infohash)
|
||||||
|
external
|
||||||
|
onlyController
|
||||||
|
{
|
||||||
|
_setKernel(_kernel, _infohash);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVersion(uint256 index) public view
|
||||||
|
returns(uint256 blockNumber,
|
||||||
|
uint256 timestamp,
|
||||||
|
address kernel,
|
||||||
|
bytes infohash)
|
||||||
|
{
|
||||||
|
return (versionLog[index].blockNumber,
|
||||||
|
versionLog[index].timestamp,
|
||||||
|
versionLog[index].kernel,
|
||||||
|
versionLog[index].infohash);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _setKernel(address _kernel, bytes _infohash)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
require(_kernel != latestKernel);
|
||||||
|
versionMap[_kernel] = versionLog.length;
|
||||||
|
versionLog.push(Version({blockNumber: block.number, timestamp: block.timestamp, kernel: _kernel, infohash: _infohash}));
|
||||||
|
latestUpdate = block.timestamp;
|
||||||
|
latestKernel = _kernel;
|
||||||
|
NewKernel(_kernel, _infohash);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
pragma solidity ^0.4.17;
|
||||||
|
|
||||||
|
import "./InstanceStorage.sol";
|
||||||
|
import "./DelegatedCall.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Instance
|
||||||
|
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||||
|
* @dev Contract that forward everything through delegatecall to defined kernel
|
||||||
|
*/
|
||||||
|
contract Instance is InstanceStorage, DelegatedCall {
|
||||||
|
|
||||||
|
function Instance(address _kernel) public {
|
||||||
|
kernel = _kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev delegatecall everything (but declared functions) to `_target()`
|
||||||
|
* @notice Verify `kernel()` code to predict behavior
|
||||||
|
*/
|
||||||
|
function () external delegated {
|
||||||
|
//all goes to kernel
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev returns kernel if kernel that is configured
|
||||||
|
* @return kernel address
|
||||||
|
*/
|
||||||
|
function targetDelegatedCall()
|
||||||
|
internal
|
||||||
|
constant
|
||||||
|
returns(address)
|
||||||
|
{
|
||||||
|
return kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
pragma solidity ^0.4.17;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title InstanceStorage
|
||||||
|
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||||
|
* @dev Defines kernel vars that Kernel contract share with Instance.
|
||||||
|
* Important to avoid overwriting wrong storage pointers is that
|
||||||
|
* InstanceStorage should be always the first contract at heritance.
|
||||||
|
*/
|
||||||
|
contract InstanceStorage {
|
||||||
|
// protected zone start (InstanceStorage vars)
|
||||||
|
address public kernel;
|
||||||
|
// protected zone end
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
pragma solidity ^0.4.17;
|
||||||
|
|
||||||
|
import "./Instance.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title UpdatableInstance
|
||||||
|
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
|
||||||
|
* @dev Contract that can be updated by a call from itself.
|
||||||
|
*/
|
||||||
|
contract UpdatableInstance is Instance {
|
||||||
|
|
||||||
|
event InstanceUpdated(address oldKernel, address newKernel);
|
||||||
|
|
||||||
|
function UpdatableInstance(address _kernel)
|
||||||
|
Instance(_kernel)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUpdatableInstance(address _kernel) external {
|
||||||
|
require(msg.sender == address(this));
|
||||||
|
InstanceUpdated(kernel, _kernel);
|
||||||
|
kernel = _kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
pragma solidity ^0.4.17;
|
||||||
|
|
||||||
|
import "../deploy/Factory.sol";
|
||||||
|
import "../deploy/UpdatableInstance.sol";
|
||||||
|
import "./BountyKernel.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract BountyFactory is Factory {
|
||||||
|
|
||||||
|
event IdentityCreated(address instance);
|
||||||
|
|
||||||
|
function BountyFactory(bytes _infohash)
|
||||||
|
public
|
||||||
|
Factory(initializeFirstVersion(), _infohash)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeFirstVersion() private returns (address a){
|
||||||
|
address[] memory dummyOwners = new address[](1);
|
||||||
|
dummyOwners[0] = address(this);
|
||||||
|
a = address(new BountyKernel(dummyOwners));
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBounty(address _pivot, address _repoOwner)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
BountyKernel instance = BountyKernel(new UpdatableInstance(address(latestKernel)));
|
||||||
|
address[] memory multisigOwners = new address[](2);
|
||||||
|
multisigOwners[0] = _pivot;
|
||||||
|
multisigOwners[1] = _repoOwner;
|
||||||
|
instance.initBounty(multisigOwners, 2);
|
||||||
|
IdentityCreated(address(instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
pragma solidity ^0.4.17;
|
||||||
|
|
||||||
|
import "../deploy/InstanceStorage.sol";
|
||||||
|
import "./MultiSigTokenWallet.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
contract BountyKernel is InstanceStorage, MultiSigTokenWallet {
|
||||||
|
|
||||||
|
|
||||||
|
function BountyKernel(address[] _dummyOwners) MultiSigTokenWallet(_dummyOwners,1) public {
|
||||||
|
//remove ownership of Kernel
|
||||||
|
uint len = _dummyOwners.length;
|
||||||
|
for (uint i = 0; i < len; i++) {
|
||||||
|
delete isOwner[_dummyOwners[i]];
|
||||||
|
}
|
||||||
|
delete owners;
|
||||||
|
//keep required > 0 to prevent initialization
|
||||||
|
required = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev Instance constructor sets initial owners and required number of confirmations.
|
||||||
|
/// @param _owners List of initial owners.
|
||||||
|
/// @param _required Number of required confirmations.
|
||||||
|
function initBounty(address[] _owners, uint _required) external {
|
||||||
|
require(owners.length == 0 && required == 0);
|
||||||
|
uint len = _owners.length;
|
||||||
|
for (uint i = 0; i < len; i++) {
|
||||||
|
require(!isOwner[_owners[i]] && _owners[i] != 0);
|
||||||
|
isOwner[_owners[i]] = true;
|
||||||
|
}
|
||||||
|
owners = _owners;
|
||||||
|
required = _required;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
pragma solidity ^0.4.15;
|
pragma solidity ^0.4.15;
|
||||||
|
|
||||||
import "./ERC20Token.sol";
|
import "../token/ERC20Token.sol";
|
||||||
|
|
||||||
contract MultiSigTokenWallet {
|
contract MultiSigTokenWallet {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
pragma solidity ^0.4.14;
|
pragma solidity ^0.4.18;
|
||||||
|
|
||||||
|
import "./ERC20Token.sol";
|
||||||
|
|
||||||
/// @title Test token contract - Allows testing of token transfers with multisig wallet.
|
/// @title Test token contract - Allows testing of token transfers with multisig wallet.
|
||||||
contract TestToken {
|
contract TestToken is ERC20Token {
|
||||||
|
|
||||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||||
|
@ -14,7 +16,7 @@ contract TestToken {
|
||||||
string public symbol;
|
string public symbol;
|
||||||
uint8 public decimals;
|
uint8 public decimals;
|
||||||
|
|
||||||
function TestToken(string _name, string _symbol, uint8 _decimals) {
|
function TestToken(string _name, string _symbol, uint8 _decimals) public {
|
||||||
require(bytes(_name).length > 0);
|
require(bytes(_name).length > 0);
|
||||||
require(bytes(_symbol).length > 0);
|
require(bytes(_symbol).length > 0);
|
||||||
name = _name;
|
name = _name;
|
Loading…
Reference in New Issue