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;
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
|
|
||||||
contract UserAuthority {
|
import "./UserProxy.sol";
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProxyRegistry
|
// ProxyRegistry
|
||||||
contract ProxyRegistry {
|
contract ProxyRegistry {
|
||||||
|
@ -145,15 +15,18 @@ contract ProxyRegistry {
|
||||||
|
|
||||||
// deploys a new proxy instance
|
// deploys a new proxy instance
|
||||||
// sets owner of proxy to caller
|
// sets owner of proxy to caller
|
||||||
function build() public returns (UserProxy proxy) {
|
function build(uint activeDays) public returns (UserProxy proxy) {
|
||||||
proxy = build(msg.sender);
|
proxy = build(msg.sender, activeDays);
|
||||||
}
|
}
|
||||||
|
|
||||||
// deploys a new proxy instance
|
// deploys a new proxy instance
|
||||||
// sets custom owner of proxy
|
// sets custom owner of proxy
|
||||||
function build(address owner) public returns (UserProxy proxy) {
|
function build(address owner, uint activeDays) 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
|
require(
|
||||||
proxy = new UserProxy(logicProxyAddr);
|
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));
|
emit Created(msg.sender, owner, address(proxy));
|
||||||
proxy.setOwner(owner);
|
proxy.setOwner(owner);
|
||||||
proxies[owner] = proxy;
|
proxies[owner] = proxy;
|
||||||
|
|
|
@ -1,58 +1,56 @@
|
||||||
pragma solidity ^0.4.23;
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
|
|
||||||
contract UserAuthority {
|
contract UserAuth {
|
||||||
function canCall(address src, address dst, bytes4 sig) public view returns (bool);
|
event LogSetOwner(address indexed owner, bool isGuardian);
|
||||||
}
|
event LogSetGuardian(address indexed guardian);
|
||||||
|
|
||||||
contract UserAuthEvents {
|
mapping(uint => address) public guardians;
|
||||||
event LogSetAuthority (address indexed authority);
|
address public owner;
|
||||||
event LogSetOwner (address indexed owner);
|
uint public lastActivity; // timestamp
|
||||||
}
|
uint public activePeriod; // timestamp // guardians can set owner after owner stay inactive for certain period
|
||||||
|
|
||||||
contract UserAuth is UserAuthEvents {
|
|
||||||
UserAuthority public authority;
|
|
||||||
address public owner;
|
|
||||||
|
|
||||||
constructor() public {
|
constructor() public {
|
||||||
owner = msg.sender;
|
owner = msg.sender;
|
||||||
emit LogSetOwner(msg.sender);
|
emit LogSetOwner(msg.sender, false);
|
||||||
}
|
|
||||||
|
|
||||||
function setOwner(address owner_)
|
|
||||||
public
|
|
||||||
auth
|
|
||||||
{
|
|
||||||
owner = owner_;
|
|
||||||
emit LogSetOwner(owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setAuthority(UserAuthority authority_)
|
|
||||||
public
|
|
||||||
auth
|
|
||||||
{
|
|
||||||
authority = authority_;
|
|
||||||
emit LogSetAuthority(authority);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier auth {
|
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)) {
|
if (src == address(this)) {
|
||||||
return true;
|
return true;
|
||||||
} else if (src == owner) {
|
} else if (src == owner) {
|
||||||
return true;
|
return true;
|
||||||
} else if (authority == UserAuthority(0)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
} 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 {
|
contract UserNote {
|
||||||
event LogNote(
|
event LogNote(
|
||||||
bytes4 indexed sig,
|
bytes4 indexed sig,
|
||||||
|
@ -66,14 +64,11 @@ contract UserNote {
|
||||||
modifier note {
|
modifier note {
|
||||||
bytes32 foo;
|
bytes32 foo;
|
||||||
bytes32 bar;
|
bytes32 bar;
|
||||||
|
|
||||||
assembly {
|
assembly {
|
||||||
foo := calldataload(4)
|
foo := calldataload(4)
|
||||||
bar := calldataload(36)
|
bar := calldataload(36)
|
||||||
}
|
}
|
||||||
|
|
||||||
emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
|
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);
|
function getLogic(address logicAddr) external view returns(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checking if the logic proxy is authorised
|
||||||
contract LogicProxy {
|
contract LogicProxy {
|
||||||
address public logicProxyAddr;
|
address public logicProxyAddr;
|
||||||
|
function isAuthLogic(address logicAddr) internal view returns(bool) {
|
||||||
function isLogic(address logicAddr) internal view returns(bool) {
|
|
||||||
LogicRegistry logicProxy = LogicRegistry(logicProxyAddr);
|
LogicRegistry logicProxy = LogicRegistry(logicProxyAddr);
|
||||||
return logicProxy.getLogic(logicAddr);
|
return logicProxy.getLogic(logicAddr);
|
||||||
}
|
}
|
||||||
|
@ -98,8 +93,10 @@ contract LogicProxy {
|
||||||
// i.e. a multisig
|
// i.e. a multisig
|
||||||
contract UserProxy is UserAuth, UserNote, LogicProxy {
|
contract UserProxy is UserAuth, UserNote, LogicProxy {
|
||||||
|
|
||||||
constructor(address logicProxyAddr_) public {
|
constructor(address logicProxyAddr_, uint activePeriod_) public {
|
||||||
logicProxyAddr = logicProxyAddr_;
|
logicProxyAddr = logicProxyAddr_;
|
||||||
|
lastActivity = block.timestamp;
|
||||||
|
activePeriod = activePeriod_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function() external payable {}
|
function() external payable {}
|
||||||
|
@ -112,8 +109,7 @@ contract UserProxy is UserAuth, UserNote, LogicProxy {
|
||||||
returns (bytes memory response)
|
returns (bytes memory response)
|
||||||
{
|
{
|
||||||
require(_target != address(0), "user-proxy-target-address-required");
|
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
|
// call contract in current context
|
||||||
assembly {
|
assembly {
|
||||||
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
|
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user