mirror of
https://github.com/Instadapp/smart-contract.git
synced 2024-07-29 22:08:07 +00:00
Added usecase based logics in user proxy.
This commit is contained in:
parent
0666a6b72e
commit
aca3d9bf1e
|
@ -8,6 +8,7 @@ contract AddressRegistry {
|
||||||
|
|
||||||
constructor() public {
|
constructor() public {
|
||||||
registry[keccak256(abi.encodePacked("admin"))] = msg.sender;
|
registry[keccak256(abi.encodePacked("admin"))] = msg.sender;
|
||||||
|
registry[keccak256(abi.encodePacked("owner"))] = msg.sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAddr(string memory name) public view returns(address) {
|
function getAddr(string memory name) public view returns(address) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
pragma solidity ^0.4.23;
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
|
|
||||||
interface AddrRegistry {
|
interface AddrRegistry {
|
||||||
function getAddr(string calldata name) external view returns(address);
|
function getAddr(string calldata name) external view returns(address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
// DSProxyCache
|
|
||||||
// This global cache stores addresses of contracts previously deployed
|
|
||||||
// by a proxy. This saves gas from repeat deployment of the same
|
|
||||||
// contracts and eliminates blockchain bloat.
|
|
||||||
|
|
||||||
// By default, all proxies deployed from the same factory store
|
|
||||||
// contracts in the same cache. The cache a proxy instance uses can be
|
|
||||||
// changed. The cache uses the sha3 hash of a contract's bytecode to
|
|
||||||
// lookup the address
|
|
||||||
pragma solidity ^0.4.23;
|
|
||||||
|
|
||||||
contract DSProxyCache {
|
|
||||||
mapping(bytes32 => address) cache;
|
|
||||||
|
|
||||||
function read(bytes _code) public view returns (address) {
|
|
||||||
bytes32 hash = keccak256(_code);
|
|
||||||
return cache[hash];
|
|
||||||
}
|
|
||||||
|
|
||||||
function write(bytes _code) public returns (address target) {
|
|
||||||
assembly {
|
|
||||||
target := create(0, add(_code, 0x20), mload(_code))
|
|
||||||
switch iszero(extcodesize(target))
|
|
||||||
case 1 {
|
|
||||||
// throw if contract failed to deploy
|
|
||||||
revert(0, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytes32 hash = keccak256(_code);
|
|
||||||
cache[hash] = target;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
pragma solidity ^0.4.23;
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
|
|
||||||
contract UserAuthority {
|
contract UserAuthority {
|
||||||
function canCall(address src, address dst, bytes4 sig) public view returns (bool);
|
function canCall(address src, address dst, bytes4 sig) public view returns (bool);
|
||||||
}
|
}
|
||||||
|
@ -77,35 +78,31 @@ contract UserNote {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// UserProxy
|
||||||
// Allows code execution using a persistant identity This can be very
|
// Allows code execution using a persistant identity This can be very
|
||||||
// useful to execute a sequence of atomic actions. Since the owner of
|
// useful to execute a sequence of atomic actions. Since the owner of
|
||||||
// the proxy can be changed, this allows for dynamic ownership models
|
// the proxy can be changed, this allows for dynamic ownership models
|
||||||
// i.e. a multisig
|
// i.e. a multisig
|
||||||
contract UserProxy is UserAuth, UserNote {
|
contract UserProxy is UserAuth, UserNote, LogicProxy {
|
||||||
UserProxyCache public cache; // global cache for contracts
|
|
||||||
|
|
||||||
constructor(address _cacheAddr) public {
|
constructor(address logicProxyAddr_) public {
|
||||||
setCache(_cacheAddr);
|
logicProxyAddr = logicProxyAddr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function() external payable {
|
function() external payable {}
|
||||||
}
|
|
||||||
|
|
||||||
// use the proxy to execute calldata _data on contract _code
|
|
||||||
function execute(bytes memory _code, bytes memory _data)
|
|
||||||
public
|
|
||||||
payable
|
|
||||||
returns (address target, bytes memory response)
|
|
||||||
{
|
|
||||||
target = cache.read(_code);
|
|
||||||
if (target == address(0)) {
|
|
||||||
// deploy contract & store its address in cache
|
|
||||||
target = cache.write(_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
response = execute(target, _data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute(address _target, bytes memory _data)
|
function execute(address _target, bytes memory _data)
|
||||||
public
|
public
|
||||||
|
@ -114,7 +111,8 @@ contract UserProxy is UserAuth, UserNote {
|
||||||
payable
|
payable
|
||||||
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");
|
||||||
|
|
||||||
// call contract in current context
|
// call contract in current context
|
||||||
assembly {
|
assembly {
|
||||||
|
@ -133,68 +131,29 @@ contract UserProxy is UserAuth, UserNote {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//set new cache
|
|
||||||
function setCache(address _cacheAddr)
|
|
||||||
public
|
|
||||||
auth
|
|
||||||
note
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
require(_cacheAddr != address(0), "User-proxy-cache-address-required");
|
|
||||||
cache = UserProxyCache(_cacheAddr); // overwrite cache
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserProxyCache
|
|
||||||
// This global cache stores addresses of contracts previously deployed
|
|
||||||
// by a proxy. This saves gas from repeat deployment of the same
|
|
||||||
// contracts and eliminates blockchain bloat.
|
|
||||||
|
|
||||||
// By default, all proxies deployed from the same factory store
|
|
||||||
// contracts in the same cache. The cache a proxy instance uses can be
|
|
||||||
// changed. The cache uses the sha3 hash of a contract's bytecode to
|
|
||||||
// lookup the address
|
|
||||||
contract UserProxyCache {
|
|
||||||
mapping(bytes32 => address) cache;
|
|
||||||
|
|
||||||
function read(bytes memory _code) public view returns (address) {
|
|
||||||
bytes32 hash = keccak256(_code);
|
|
||||||
return cache[hash];
|
|
||||||
}
|
|
||||||
|
|
||||||
function write(bytes memory _code) public returns (address target) {
|
|
||||||
assembly {
|
|
||||||
target := create(0, add(_code, 0x20), mload(_code))
|
|
||||||
switch iszero(extcodesize(target))
|
|
||||||
case 1 {
|
|
||||||
// throw if contract failed to deploy
|
|
||||||
revert(0, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytes32 hash = keccak256(_code);
|
|
||||||
cache[hash] = target;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProxyRegistry
|
// ProxyRegistry
|
||||||
contract ProxyRegistry {
|
contract ProxyRegistry {
|
||||||
event Created(address indexed sender, address indexed owner, address proxy);
|
event Created(address indexed sender, address indexed owner, address proxy);
|
||||||
mapping(address => DSProxy) public proxies;
|
mapping(address => UserProxy) public proxies;
|
||||||
DSProxyCache cache = new DSProxyCache();
|
address public logicProxyAddr;
|
||||||
|
|
||||||
|
constructor(address logicProxyAddr_) public {
|
||||||
|
logicProxyAddr = logicProxyAddr_;
|
||||||
|
}
|
||||||
|
|
||||||
// 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 (DSProxy proxy) {
|
function build() public returns (UserProxy proxy) {
|
||||||
proxy = build(msg.sender);
|
proxy = build(msg.sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 (DSProxy proxy) {
|
function build(address owner) public returns (UserProxy proxy) {
|
||||||
require(proxies[owner] == DSProxy(0) || proxies[owner].owner() != owner); // Not allow new proxy if the user already has one and remains being the owner
|
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 DSProxy(cache);
|
proxy = new UserProxy(logicProxyAddr);
|
||||||
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,5 +1,6 @@
|
||||||
pragma solidity ^0.4.23;
|
pragma solidity ^0.4.23;
|
||||||
|
|
||||||
|
|
||||||
contract UserAuthority {
|
contract UserAuthority {
|
||||||
function canCall(address src, address dst, bytes4 sig) public view returns (bool);
|
function canCall(address src, address dst, bytes4 sig) public view returns (bool);
|
||||||
}
|
}
|
||||||
|
@ -77,35 +78,31 @@ contract UserNote {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// UserProxy
|
||||||
// Allows code execution using a persistant identity This can be very
|
// Allows code execution using a persistant identity This can be very
|
||||||
// useful to execute a sequence of atomic actions. Since the owner of
|
// useful to execute a sequence of atomic actions. Since the owner of
|
||||||
// the proxy can be changed, this allows for dynamic ownership models
|
// the proxy can be changed, this allows for dynamic ownership models
|
||||||
// i.e. a multisig
|
// i.e. a multisig
|
||||||
contract UserProxy is UserAuth, UserNote {
|
contract UserProxy is UserAuth, UserNote, LogicProxy {
|
||||||
UserProxyCache public cache; // global cache for contracts
|
|
||||||
|
|
||||||
constructor(address _cacheAddr) public {
|
constructor(address logicProxyAddr_) public {
|
||||||
setCache(_cacheAddr);
|
logicProxyAddr = logicProxyAddr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function() external payable {
|
function() external payable {}
|
||||||
}
|
|
||||||
|
|
||||||
// use the proxy to execute calldata _data on contract _code
|
|
||||||
function execute(bytes memory _code, bytes memory _data)
|
|
||||||
public
|
|
||||||
payable
|
|
||||||
returns (address target, bytes memory response)
|
|
||||||
{
|
|
||||||
target = cache.read(_code);
|
|
||||||
if (target == address(0)) {
|
|
||||||
// deploy contract & store its address in cache
|
|
||||||
target = cache.write(_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
response = execute(target, _data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute(address _target, bytes memory _data)
|
function execute(address _target, bytes memory _data)
|
||||||
public
|
public
|
||||||
|
@ -114,7 +111,8 @@ contract UserProxy is UserAuth, UserNote {
|
||||||
payable
|
payable
|
||||||
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");
|
||||||
|
|
||||||
// call contract in current context
|
// call contract in current context
|
||||||
assembly {
|
assembly {
|
||||||
|
@ -133,47 +131,4 @@ contract UserProxy is UserAuth, UserNote {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//set new cache
|
|
||||||
function setCache(address _cacheAddr)
|
|
||||||
public
|
|
||||||
auth
|
|
||||||
note
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
require(_cacheAddr != address(0), "User-proxy-cache-address-required");
|
|
||||||
cache = UserProxyCache(_cacheAddr); // overwrite cache
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserProxyCache
|
|
||||||
// This global cache stores addresses of contracts previously deployed
|
|
||||||
// by a proxy. This saves gas from repeat deployment of the same
|
|
||||||
// contracts and eliminates blockchain bloat.
|
|
||||||
|
|
||||||
// By default, all proxies deployed from the same factory store
|
|
||||||
// contracts in the same cache. The cache a proxy instance uses can be
|
|
||||||
// changed. The cache uses the sha3 hash of a contract's bytecode to
|
|
||||||
// lookup the address
|
|
||||||
contract UserProxyCache {
|
|
||||||
mapping(bytes32 => address) cache;
|
|
||||||
|
|
||||||
function read(bytes memory _code) public view returns (address) {
|
|
||||||
bytes32 hash = keccak256(_code);
|
|
||||||
return cache[hash];
|
|
||||||
}
|
|
||||||
|
|
||||||
function write(bytes memory _code) public returns (address target) {
|
|
||||||
assembly {
|
|
||||||
target := create(0, add(_code, 0x20), mload(_code))
|
|
||||||
switch iszero(extcodesize(target))
|
|
||||||
case 1 {
|
|
||||||
// throw if contract failed to deploy
|
|
||||||
revert(0, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytes32 hash = keccak256(_code);
|
|
||||||
cache[hash] = target;
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user