Skip to content

Instantly share code, notes, and snippets.



Last active Jul 27, 2018
What would you like to do?
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!
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 {
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);
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
} 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