-
Notifications
You must be signed in to change notification settings - Fork 2
/
Account.sol
121 lines (97 loc) · 2.86 KB
/
Account.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import {SignatureRSV, EthereumUtils} from "@oasisprotocol/sapphire-contracts/contracts/EthereumUtils.sol";
import {EIP155Signer} from "@oasisprotocol/sapphire-contracts/contracts/EIP155Signer.sol";
import {CloneFactory} from "./lib/CloneFactory.sol";
contract AccountFactory is CloneFactory {
Account private account;
constructor () {
account = new Account();
}
function clone (address starterOwner)
public
returns (Account acct)
{
acct = Account(createClone(address(account)));
acct.init(starterOwner);
}
}
contract Account {
bool private _initialized;
mapping(address => bool) private _controllers;
address public keypairAddress;
bytes32 private keypairSecret;
constructor () {
_initialized = true;
}
function isController (address who)
public view
returns (bool)
{
return _controllers[who];
}
function init (address starterOwner)
public
{
require( ! _initialized, "AlreadyInitialized" );
_controllers[starterOwner] = true;
(keypairAddress, keypairSecret) = EthereumUtils.generateKeypair();
_controllers[keypairAddress] = true;
_initialized = true;
}
modifier onlyByController ()
{
require( _controllers[msg.sender] == true, "OnlyByController" );
_;
}
function modifyController(address who, bool status)
public
onlyByController
{
_controllers[who] = status;
}
function signEIP155 (EIP155Signer.EthTx calldata txToSign)
public view
onlyByController
returns (bytes memory)
{
return EIP155Signer.sign(keypairAddress, keypairSecret, txToSign);
}
function sign (bytes32 digest)
public view
onlyByController
returns (SignatureRSV memory)
{
return EthereumUtils.sign(keypairAddress, keypairSecret, digest);
}
function transfer (address in_target, uint256 amount)
public
onlyByController
{
return payable(in_target).transfer(amount);
}
function call (address in_contract, bytes calldata in_data)
public
onlyByController
returns (bytes memory out_data)
{
bool success;
(success, out_data) = in_contract.call(in_data);
assembly {
switch success
case 0 { revert(add(out_data,32),mload(out_data)) }
}
}
function staticcall (address in_contract, bytes calldata in_data)
public view
onlyByController
returns (bytes memory out_data)
{
bool success;
(success, out_data) = in_contract.staticcall(in_data);
assembly {
switch success
case 0 { revert(add(out_data,32),mload(out_data)) }
}
}
}