Skip to content

Commit

Permalink
Actor app: implement permissioned forwarding
Browse files Browse the repository at this point in the history
  • Loading branch information
izqui committed Nov 16, 2018
1 parent 1fa6386 commit 7a4dd5b
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
28 changes: 27 additions & 1 deletion future-apps/actor/contracts/Actor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ pragma solidity 0.4.24;

import "@aragon/apps-vault/contracts/Vault.sol";

import "@aragon/os/contracts/common/IForwarder.sol";

contract Actor is Vault {

contract Actor is Vault, IForwarder {
bytes32 public constant EXECUTE_ROLE = keccak256("EXECUTE_ROLE");
bytes32 public constant RUN_SCRIPT_ROLE = keccak256("RUN_SCRIPT_ROLE");

string private constant ERROR_EXECUTE_ETH_NO_DATA = "VAULT_EXECUTE_ETH_NO_DATA";
string private constant ERROR_EXECUTE_TARGET_NOT_CONTRACT = "VAULT_EXECUTE_TARGET_NOT_CONTRACT";
Expand Down Expand Up @@ -48,6 +51,29 @@ contract Actor is Vault {
}
}

function isForwarder() external pure returns (bool) {
return true;
}

function forward(bytes _evmScript)
authP(RUN_SCRIPT_ROLE, arr(getScriptACLParam(_evmScript)))
public
{
bytes memory input = ""; // no input
address[] memory blacklist = new address[](0); // no addr blacklist, can interact with anything
runScript(_evmScript, input, blacklist);
}

function canForward(address sender, bytes evmScript) public view returns (bool) {
uint256[] memory params = new uint256[](1);
params[0] = getScriptACLParam(evmScript);
return canPerform(sender, RUN_SCRIPT_ROLE, params);
}

function getScriptACLParam(bytes evmScript) internal pure returns (uint256) {
return uint256(keccak256(abi.encodePacked(evmScript)));
}

function getSig(bytes data) internal pure returns (bytes4 sig) {
assembly { sig := add(data, 0x20) }
}
Expand Down
36 changes: 35 additions & 1 deletion future-apps/actor/test/actor.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { assertRevert, assertInvalidOpcode } = require('@aragon/test-helpers/asse
const { hash } = require('eth-ens-namehash')
const getBalance = require('@aragon/test-helpers/balance')(web3)
const web3Call = require('@aragon/test-helpers/call')(web3)
const { encodeCallScript, EMPTY_SCRIPT } = require('@aragon/test-helpers/evmScript')
const getEvent = (receipt, event, arg) => { return receipt.logs.filter(l => l.event == event)[0].args[arg] }

const ACL = artifacts.require('ACL')
Expand All @@ -26,7 +27,7 @@ const NULL_ADDRESS = '0x00'
contract('Actor app', (accounts) => {
let daoFact, actorBase, acl, actor, actorId

let ETH, ANY_ENTITY, APP_MANAGER_ROLE, EXECUTE_ROLE
let ETH, ANY_ENTITY, APP_MANAGER_ROLE, EXECUTE_ROLE, RUN_SCRIPT_ROLE

const root = accounts[0]

Expand All @@ -44,6 +45,7 @@ contract('Actor app', (accounts) => {
ANY_ENTITY = await aclBase.ANY_ENTITY()
APP_MANAGER_ROLE = await kernelBase.APP_MANAGER_ROLE()
EXECUTE_ROLE = await actorBase.EXECUTE_ROLE()
RUN_SCRIPT_ROLE = await actorBase.RUN_SCRIPT_ROLE()

const ethConstant = await EtherTokenConstantMock.new()
ETH = await ethConstant.getETHConstant()
Expand Down Expand Up @@ -84,6 +86,7 @@ contract('Actor app', (accounts) => {
const { to, data } = encodeFunctionCall(executionTarget, 'setCounter', N)
await actor.execute(to, 0, data, { from: executor })

// TODO: assert Execute event
assert.equal(await executionTarget.counter(), N)
})

Expand Down Expand Up @@ -172,4 +175,35 @@ contract('Actor app', (accounts) => {
})
})
})

context('running scripts', () => {
let executionTarget, script
const [nonScriptRunner, scriptRunner] = accounts

beforeEach(async () => {
executionTarget = await ExecutionTarget.new()
// prepare script
const action = { to: executionTarget.address, calldata: executionTarget.contract.execute.getData() }
script = encodeCallScript([action, action]) // perform action twice

await acl.createPermission(scriptRunner, actor.address, RUN_SCRIPT_ROLE, root, { from: root })
})

it('runs script', async () => {
assert.isTrue(await actor.canForward(scriptRunner, script))
assert.equal(await executionTarget.counter(), 0)

await actor.forward(script, { from: scriptRunner })

assert.equal(await executionTarget.counter(), 2)
})

it('fails to run script without permissions', async () => {
assert.isFalse(await actor.canForward(nonScriptRunner, script))

await assertRevert(() =>
actor.forward(script, { from: nonScriptRunner })
)
})
})
})

0 comments on commit 7a4dd5b

Please sign in to comment.