Last active
July 27, 2018 17:09
-
-
Save izqui/27f228b13671f687f194676436b23aac to your computer and use it in GitHub Desktop.
Prototype of Aragon app that can be used for interacting with other protocols and external contracts. 🚨Unaudited and experimental code, do not deploy to production!
This file contains 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
pragma solidity 0.4.18; | |
import "./Vault.sol"; | |
contract Actor is Vault { | |
bytes32 constant public PERFORM_ACTION_ROLE = keccak256("PERFORM_ACTION_ROLE"); | |
bytes32 constant public RETURN_TO_PARENT_ROLE = keccak256("RETURN_TO_PARENT_ROLE"); | |
bytes4 constant internal ERC20_TRANSFER_SIG = 0xa9059cbb; // bytes4(keccak256("transfer(address,uint256)")) | |
Vault public parentVault; | |
event PerformAction(address indexed target, uint256 ethAmount, bytes data, bytes returnData); | |
event ReturnToParentVault(address indexed parentVault, address indexed token, uint256 value); | |
function initialize(Vault _parentVault) onlyInit public { | |
initialized(); | |
parentVault = _parentVault; | |
} | |
function performAction(address _target, uint256 _ethAmount, bytes _data) | |
authP(PERFORM_ACTION_ROLE, arr(_target, _ethAmount, uint256(getSig(_data)))) public returns (bytes) { | |
// TODO: are this checks even needed?? | |
// ERC20 transfers are disallowed through performAction (vault.transfer()) should be used instead | |
// Note that they could still be done using erc20.approve + erc20.transferFrom, but | |
// this could be useful for actions such as staking tokens. These signatures can be | |
// disallowed by ACL params. | |
require(getSig(_data) != ERC20_TRANSFER_SIG); | |
if (_ethAmount > 0) { | |
// eth transfers without data should be done using vault.transfer() | |
// TODO: vault.transfer() should stop allowing sending ETH with calldata | |
require(_data.length > 0); | |
} | |
require(_target.call.value(_ethAmount)(_data)); | |
bytes memory returnData; | |
assembly { | |
returnData := mload(0x40) | |
let size := returndatasize | |
mstore(0x40, add(returnData, add(0x20, size))) | |
mstore(returnData, size) | |
returndatacopy(add(returnData, 0x20), 0, size) | |
} | |
PerformAction(_target, _ethAmount, _data, returnData); | |
return returnData; | |
} | |
function returnToParentVault(address _token, uint256 _value) authP(RETURN_TO_PARENT_ROLE, arr(_token, _value)) public { | |
if (_token == ETH) { | |
// make sure it triggers a deposit in the parent vault | |
// .send and .transfer would only use 2.3k gas which would be intercepted by the proxy | |
require(parentVault.call.value(_value)()); | |
} else { | |
ERC20(_token).approve(parentVault, _value); | |
parentVault.deposit(_token, this, _value); | |
} | |
ReturnToParentVault(parentVault, _token, _value); | |
} | |
function getSig(bytes _data) internal pure returns (bytes4 sig) { | |
assembly { | |
sig := mload(add(_data, 0x20)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment