mirror of
https://github.com/Instadapp/smart-contract.git
synced 2024-07-29 22:08:07 +00:00
Added logics for guardians in user proxy.
This commit is contained in:
parent
aca3d9bf1e
commit
42bd657991
13
ProxyLogics/sendETH.sol
Normal file
13
ProxyLogics/sendETH.sol
Normal file
|
@ -0,0 +1,13 @@
|
|||
pragma solidity ^0.4.23;
|
||||
|
||||
|
||||
contract ProxyTest {
|
||||
|
||||
event ETHSent(uint amt);
|
||||
|
||||
function sendETH() public payable {
|
||||
address(msg.sender).transfer(msg.value);
|
||||
emit ETHSent(msg.value);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,137 +1,7 @@
|
|||
pragma solidity ^0.4.23;
|
||||
|
||||
|
||||
contract UserAuthority {
|
||||
function canCall(address src, address dst, bytes4 sig) public view returns (bool);
|
||||
}
|
||||
|
||||
contract UserAuthEvents {
|
||||
event LogSetAuthority (address indexed authority);
|
||||
event LogSetOwner (address indexed owner);
|
||||
}
|
||||
|
||||
contract UserAuth is UserAuthEvents {
|
||||
UserAuthority public authority;
|
||||
address public owner;
|
||||
|
||||
constructor() public {
|
||||
owner = msg.sender;
|
||||
emit LogSetOwner(msg.sender);
|
||||
}
|
||||
|
||||
function setOwner(address owner_)
|
||||
public
|
||||
auth
|
||||
{
|
||||
owner = owner_;
|
||||
emit LogSetOwner(owner);
|
||||
}
|
||||
|
||||
function setAuthority(UserAuthority authority_)
|
||||
public
|
||||
auth
|
||||
{
|
||||
authority = authority_;
|
||||
emit LogSetAuthority(authority);
|
||||
}
|
||||
|
||||
modifier auth {
|
||||
require(isAuthorized(msg.sender, msg.sig));
|
||||
_;
|
||||
}
|
||||
|
||||
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
|
||||
if (src == address(this)) {
|
||||
return true;
|
||||
} else if (src == owner) {
|
||||
return true;
|
||||
} else if (authority == UserAuthority(0)) {
|
||||
return false;
|
||||
} else {
|
||||
return authority.canCall(src, this, sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contract UserNote {
|
||||
event LogNote(
|
||||
bytes4 indexed sig,
|
||||
address indexed guy,
|
||||
bytes32 indexed foo,
|
||||
bytes32 indexed bar,
|
||||
uint wad,
|
||||
bytes fax
|
||||
) anonymous;
|
||||
|
||||
modifier note {
|
||||
bytes32 foo;
|
||||
bytes32 bar;
|
||||
|
||||
assembly {
|
||||
foo := calldataload(4)
|
||||
bar := calldataload(36)
|
||||
}
|
||||
|
||||
emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
|
||||
|
||||
_;
|
||||
}
|
||||
}
|
||||
|
||||
interface LogicRegistry {
|
||||
function getLogic(address logicAddr) external view returns(bool);
|
||||
}
|
||||
|
||||
contract LogicProxy {
|
||||
address public logicProxyAddr;
|
||||
|
||||
function isLogic(address logicAddr) internal view returns(bool) {
|
||||
LogicRegistry logicProxy = LogicRegistry(logicProxyAddr);
|
||||
return logicProxy.getLogic(logicAddr);
|
||||
}
|
||||
}
|
||||
|
||||
// UserProxy
|
||||
// Allows code execution using a persistant identity This can be very
|
||||
// useful to execute a sequence of atomic actions. Since the owner of
|
||||
// the proxy can be changed, this allows for dynamic ownership models
|
||||
// i.e. a multisig
|
||||
contract UserProxy is UserAuth, UserNote, LogicProxy {
|
||||
|
||||
constructor(address logicProxyAddr_) public {
|
||||
logicProxyAddr = logicProxyAddr_;
|
||||
}
|
||||
|
||||
function() external payable {}
|
||||
|
||||
function execute(address _target, bytes memory _data)
|
||||
public
|
||||
auth
|
||||
note
|
||||
payable
|
||||
returns (bytes memory response)
|
||||
{
|
||||
require(_target != address(0), "user-proxy-target-address-required");
|
||||
require(isLogic(_target), "invalid-logic-proxy-address");
|
||||
|
||||
// call contract in current context
|
||||
assembly {
|
||||
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
|
||||
let size := returndatasize
|
||||
|
||||
response := mload(0x40)
|
||||
mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))
|
||||
mstore(response, size)
|
||||
returndatacopy(add(response, 0x20), 0, size)
|
||||
|
||||
switch iszero(succeeded)
|
||||
case 1 {
|
||||
// throw if delegatecall failed
|
||||
revert(add(response, 0x20), size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
import "./UserProxy.sol";
|
||||
|
||||
// ProxyRegistry
|
||||
contract ProxyRegistry {
|
||||
|
@ -145,15 +15,18 @@ contract ProxyRegistry {
|
|||
|
||||
// deploys a new proxy instance
|
||||
// sets owner of proxy to caller
|
||||
function build() public returns (UserProxy proxy) {
|
||||
proxy = build(msg.sender);
|
||||
function build(uint activeDays) public returns (UserProxy proxy) {
|
||||
proxy = build(msg.sender, activeDays);
|
||||
}
|
||||
|
||||
// deploys a new proxy instance
|
||||
// sets custom owner of proxy
|
||||
function build(address owner) public returns (UserProxy proxy) {
|
||||
require(proxies[owner] == UserProxy(0) || proxies[owner].owner() != owner); // Not allow new proxy if the user already has one and remains being the owner
|
||||
proxy = new UserProxy(logicProxyAddr);
|
||||
function build(address owner, uint activeDays) public returns (UserProxy proxy) {
|
||||
require(
|
||||
proxies[owner] == UserProxy(0) || proxies[owner].owner() != owner,
|
||||
"multiple-proxy-per-user-not-allowed"
|
||||
); // Not allow new proxy if the user already has one and remains being the owner
|
||||
proxy = new UserProxy(logicProxyAddr, activeDays);
|
||||
emit Created(msg.sender, owner, address(proxy));
|
||||
proxy.setOwner(owner);
|
||||
proxies[owner] = proxy;
|
||||
|
|
|
@ -1,58 +1,56 @@
|
|||
pragma solidity ^0.4.23;
|
||||
|
||||
|
||||
contract UserAuthority {
|
||||
function canCall(address src, address dst, bytes4 sig) public view returns (bool);
|
||||
}
|
||||
contract UserAuth {
|
||||
event LogSetOwner(address indexed owner, bool isGuardian);
|
||||
event LogSetGuardian(address indexed guardian);
|
||||
|
||||
contract UserAuthEvents {
|
||||
event LogSetAuthority (address indexed authority);
|
||||
event LogSetOwner (address indexed owner);
|
||||
}
|
||||
|
||||
contract UserAuth is UserAuthEvents {
|
||||
UserAuthority public authority;
|
||||
address public owner;
|
||||
mapping(uint => address) public guardians;
|
||||
address public owner;
|
||||
uint public lastActivity; // timestamp
|
||||
uint public activePeriod; // timestamp // guardians can set owner after owner stay inactive for certain period
|
||||
|
||||
constructor() public {
|
||||
owner = msg.sender;
|
||||
emit LogSetOwner(msg.sender);
|
||||
}
|
||||
|
||||
function setOwner(address owner_)
|
||||
public
|
||||
auth
|
||||
{
|
||||
owner = owner_;
|
||||
emit LogSetOwner(owner);
|
||||
}
|
||||
|
||||
function setAuthority(UserAuthority authority_)
|
||||
public
|
||||
auth
|
||||
{
|
||||
authority = authority_;
|
||||
emit LogSetAuthority(authority);
|
||||
emit LogSetOwner(msg.sender, false);
|
||||
}
|
||||
|
||||
modifier auth {
|
||||
require(isAuthorized(msg.sender, msg.sig));
|
||||
require(isAuth(msg.sender), "permission-denied");
|
||||
_;
|
||||
}
|
||||
|
||||
function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
|
||||
function isAuth(address src) internal view returns (bool) {
|
||||
if (src == address(this)) {
|
||||
return true;
|
||||
} else if (src == owner) {
|
||||
return true;
|
||||
} else if (authority == UserAuthority(0)) {
|
||||
return false;
|
||||
} else {
|
||||
return authority.canCall(src, this, sig);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function setOwner(address owner_) public auth {
|
||||
owner = owner_;
|
||||
emit LogSetOwner(owner, false);
|
||||
}
|
||||
|
||||
function setOwnerViaGuardian(address owner_, uint num) public auth {
|
||||
require(msg.sender == guardians[num], "permission-denied");
|
||||
require(block.timestamp > (lastActivity + activePeriod), "active-period-not-over");
|
||||
owner = owner_;
|
||||
emit LogSetOwner(owner, true);
|
||||
}
|
||||
|
||||
function setGuardian(uint num, address guardian_) public auth {
|
||||
require(num > 0 && num < 6, "guardians-cant-exceed-five");
|
||||
guardians[num] = guardian_;
|
||||
emit LogSetGuardian(guardian_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
contract UserNote {
|
||||
event LogNote(
|
||||
bytes4 indexed sig,
|
||||
|
@ -66,14 +64,11 @@ contract UserNote {
|
|||
modifier note {
|
||||
bytes32 foo;
|
||||
bytes32 bar;
|
||||
|
||||
assembly {
|
||||
foo := calldataload(4)
|
||||
bar := calldataload(36)
|
||||
}
|
||||
|
||||
emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
|
||||
|
||||
_;
|
||||
}
|
||||
}
|
||||
|
@ -82,10 +77,10 @@ interface LogicRegistry {
|
|||
function getLogic(address logicAddr) external view returns(bool);
|
||||
}
|
||||
|
||||
// checking if the logic proxy is authorised
|
||||
contract LogicProxy {
|
||||
address public logicProxyAddr;
|
||||
|
||||
function isLogic(address logicAddr) internal view returns(bool) {
|
||||
function isAuthLogic(address logicAddr) internal view returns(bool) {
|
||||
LogicRegistry logicProxy = LogicRegistry(logicProxyAddr);
|
||||
return logicProxy.getLogic(logicAddr);
|
||||
}
|
||||
|
@ -98,8 +93,10 @@ contract LogicProxy {
|
|||
// i.e. a multisig
|
||||
contract UserProxy is UserAuth, UserNote, LogicProxy {
|
||||
|
||||
constructor(address logicProxyAddr_) public {
|
||||
constructor(address logicProxyAddr_, uint activePeriod_) public {
|
||||
logicProxyAddr = logicProxyAddr_;
|
||||
lastActivity = block.timestamp;
|
||||
activePeriod = activePeriod_;
|
||||
}
|
||||
|
||||
function() external payable {}
|
||||
|
@ -112,8 +109,7 @@ contract UserProxy is UserAuth, UserNote, LogicProxy {
|
|||
returns (bytes memory response)
|
||||
{
|
||||
require(_target != address(0), "user-proxy-target-address-required");
|
||||
require(isLogic(_target), "invalid-logic-proxy-address");
|
||||
|
||||
require(isAuthLogic(_target), "logic-proxy-address-not-allowed");
|
||||
// call contract in current context
|
||||
assembly {
|
||||
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
|
||||
|
|
Loading…
Reference in New Issue
Block a user