Last active
June 17, 2018 16:47
-
-
Save izqui/1f9847dddd5f399bbc3879b1cf1c69fe to your computer and use it in GitHub Desktop.
Quick spike to demonstrate a generic account proxy pattern and a specific implementation for cold/hot wallets. Not reviewed, use it at your own risk.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
contract AccountProxy { | |
event Fwded(address indexed to, uint256 value, bytes calldata, bool succeeded); | |
// must be implemented by super contract | |
function canFwd(address who, address to, uint256 value, bytes calldata) public view returns (bool); | |
function () payable {} // allow to deposit eth | |
function fwd(address to, uint256 value, bytes calldata) external { | |
require(canFwd(msg.sender, to, value, calldata)); | |
bool succeeded = to.call.value(value)(calldata); | |
emit Fwded(to, value, calldata, succeeded); | |
} | |
} | |
contract HotColdProxy is AccountProxy { | |
address public hot; | |
address public cold; | |
mapping (bytes4 => bool) onlyColdFunctions; | |
mapping (address => bool) onlyColdAddresses; | |
constructor (address _cold, address _hot, bytes4[] _onlyColdFunctions, address[] _onlyColdAddresses) public { | |
cold = _cold; | |
hot = _hot; | |
for (uint i = 0; i < _onlyColdFunctions.length; i++) { | |
onlyColdFunctions[_onlyColdFunctions[i]] = true; | |
} | |
for (uint j = 0; j < _onlyColdAddresses.length; j++) { | |
onlyColdAddresses[_onlyColdAddresses[j]] = true; | |
} | |
onlyColdAddresses[this] = true; | |
} | |
function changeHot(address _hot) external { | |
require(msg.sender == address(this)); // proxy must call itself to allow flexibility | |
hot = _hot; | |
} | |
function changeCold(address _cold) external { | |
require(msg.sender == _cold); // could also require for proxy to call itself, but it is sensible to limit it to only cold | |
cold = _cold; | |
} | |
function canFwd(address who, address to, uint256 value, bytes calldata) public view returns (bool) { | |
if (who == hot) { | |
bool onlyCold = value > 0 || onlyColdAddresses[to] || onlyColdFunctions[sig(calldata)]; | |
return !onlyCold; | |
} | |
return who == cold; | |
} | |
// TODO: Functions to change onlyCold addresses and functions | |
function sig(bytes calldata) internal pure returns (bytes4 sig) { | |
assembly { sig := mload(calldata) } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment