Skip to content

Commit

Permalink
Merge branch 'next' into extend_forwarder_interface
Browse files Browse the repository at this point in the history
  • Loading branch information
sohkai authored Jul 2, 2020
2 parents 2774a9f + e6ea55f commit f8a69d8
Show file tree
Hide file tree
Showing 22 changed files with 1,268 additions and 148 deletions.
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ If the answer to either of those two questions are "yes", then you're probably d
## Fixing issues

1. [Find an issue](https://github.com/aragon/aragonOS/issues) that you are interested in.
- You may want to ask on the issue or on Aragon Chat's [#dev channel](https://aragon.chat/channel/dev) if anyone has already started working on the issue.
- You may want to ask on the issue or in the [aragonOS Spectrum channel](https://spectrum.chat/aragon/aragonos) if anyone has already started working on the issue.
1. Fork and clone a local copy of the repository.
1. Make the appropriate changes for the issue you are trying to address or the feature that you want to add.
- Make sure to add tests!
Expand All @@ -69,4 +69,4 @@ aragonOS is generally meant to be used as a library by developers but includes c

## Community

If you need help, please reach out to Aragon core contributors and community members in the Aragon Chat [#dev](https://aragon.chat/channel/dev) [#dev-help](https://aragon.chat/channel/dev-help) channels. We'd love to hear from you and know what you're working on!
If you need help, please reach out to Aragon core contributors and community members in the [aragonOS Spectrum channel](https://spectrum.chat/aragon/aragonos). We'd love to hear from you and know what you're working on!
277 changes: 180 additions & 97 deletions contracts/acl/ACL.sol

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions contracts/acl/IACL.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@ pragma solidity ^0.4.24;
interface IACL {
function initialize(address permissionsCreator) external;

// TODO: this should be external
// See https://github.com/ethereum/solidity/issues/4832
function hasPermission(address who, address where, bytes32 what, bytes how) public view returns (bool);
function hasPermission(address who, address where, bytes32 what, bytes how) external view returns (bool);
}
16 changes: 15 additions & 1 deletion contracts/acl/IACLOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@
pragma solidity ^0.4.24;


/**
* @title ACL Oracle interface
* @dev This interface simply defines a predicate method that must be implemented by smart contracts intended to be used as ACL Oracles.
* ACL oracles should be used if you would like to protect a permission with custom logic from an external contract.
*/
interface IACLOracle {
function canPerform(address who, address where, bytes32 what, uint256[] how) external view returns (bool);
/**
* @dev Tells whether `sender` can execute `what` (and `how`) in `where` for the grantee `who`
* @param who Sender of the original call
* @param grantee Grantee of the permission being evaluated
* @param where Address of the app
* @param what Identifier for a group of actions in app (role)
* @param how Permission parameters
* @return True if the action should be accepted
*/
function canPerform(address who, address grantee, address where, bytes32 what, uint256[] how) external view returns (bool);
}
15 changes: 15 additions & 0 deletions contracts/acl/IACLOracleV1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* SPDX-License-Identifier: MIT
*/

pragma solidity ^0.4.24;


/**
* @title Previous version of the ACL Oracle interface (aragonOS@4)
* @dev This interface simply defines a predicate method that must be implemented by smart contracts intended to be used as ACL Oracles.
* ACL oracles should be used if you would like to protect a permission with custom logic from an external contract.
*/
interface IACLOracleV1 {
function canPerform(address who, address where, bytes32 what, uint256[] how) external view returns (bool);
}
161 changes: 161 additions & 0 deletions contracts/apps/disputable/DisputableAragonApp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* SPDX-License-Identifier: MIT
*/

pragma solidity ^0.4.24;

import "./IAgreement.sol";
import "./IDisputable.sol";
import "../AragonApp.sol";
import "../../lib/token/ERC20.sol";
import "../../lib/math/SafeMath64.sol";


contract DisputableAragonApp is IDisputable, AragonApp {
/* Validation errors */
string internal constant ERROR_SENDER_NOT_AGREEMENT = "DISPUTABLE_SENDER_NOT_AGREEMENT";
string internal constant ERROR_AGREEMENT_STATE_INVALID = "DISPUTABLE_AGREEMENT_STATE_INVAL";

// This role is used to protect who can challenge actions in derived Disputable apps. However, it is not required
// to be validated in the app itself as the connected Agreement is responsible for performing the check on a challenge.
// bytes32 public constant CHALLENGE_ROLE = keccak256("CHALLENGE_ROLE");
bytes32 public constant CHALLENGE_ROLE = 0xef025787d7cd1a96d9014b8dc7b44899b8c1350859fb9e1e05f5a546dd65158d;

// bytes32 public constant SET_AGREEMENT_ROLE = keccak256("SET_AGREEMENT_ROLE");
bytes32 public constant SET_AGREEMENT_ROLE = 0x8dad640ab1b088990c972676ada708447affc660890ec9fc9a5483241c49f036;

// bytes32 internal constant AGREEMENT_POSITION = keccak256("aragonOS.appStorage.agreement");
bytes32 internal constant AGREEMENT_POSITION = 0x6dbe80ccdeafbf5f3fff5738b224414f85e9370da36f61bf21c65159df7409e9;

modifier onlyAgreement() {
require(address(_getAgreement()) == msg.sender, ERROR_SENDER_NOT_AGREEMENT);
_;
}

/**
* @notice Challenge disputable action #`_disputableActionId`
* @dev This hook must be implemented by Disputable apps. We provide a base implementation to ensure that the `onlyAgreement` modifier
* is included. Developers of derived Disputable apps should implement an internal abstract implementation of the hook.
* @param _disputableActionId Identifier of the action to be challenged
* @param _challengeId Identifier of the challenge in the context of the Agreement
* @param _challenger Address that submitted the challenge
*/
function onDisputableActionChallenged(uint256 _disputableActionId, uint256 _challengeId, address _challenger) external onlyAgreement {
_onDisputableActionChallenged(_disputableActionId, _challengeId, _challenger);
}

/**
* @notice Allow disputable action #`_disputableActionId`
* @dev This hook must be implemented by Disputable apps. We provide a base implementation to ensure that the `onlyAgreement` modifier
* is included. Developers of derived Disputable apps should implement an internal abstract implementation of the hook.
* @param _disputableActionId Identifier of the action to be allowed
*/
function onDisputableActionAllowed(uint256 _disputableActionId) external onlyAgreement {
_onDisputableActionAllowed(_disputableActionId);
}

/**
* @notice Reject disputable action #`_disputableActionId`
* @dev This hook must be implemented by Disputable apps. We provide a base implementation to ensure that the `onlyAgreement` modifier
* is included. Developers of derived Disputable apps should implement an internal abstract implementation of the hook.
* @param _disputableActionId Identifier of the action to be rejected
*/
function onDisputableActionRejected(uint256 _disputableActionId) external onlyAgreement {
_onDisputableActionRejected(_disputableActionId);
}

/**
* @notice Void disputable action #`_disputableActionId`
* @dev This hook must be implemented by Disputable apps. We provide a base implementation to ensure that the `onlyAgreement` modifier
* is included. Developers of derived Disputable apps should implement an internal abstract implementation of the hook.
* @param _disputableActionId Identifier of the action to be voided
*/
function onDisputableActionVoided(uint256 _disputableActionId) external onlyAgreement {
_onDisputableActionVoided(_disputableActionId);
}

/**
* @notice Set Agreement to `_agreement`
* @param _agreement Agreement instance to be set
*/
function setAgreement(IAgreement _agreement) external auth(SET_AGREEMENT_ROLE) {
IAgreement agreement = _getAgreement();
require(agreement == IAgreement(0) && _agreement != IAgreement(0), ERROR_AGREEMENT_STATE_INVALID);

AGREEMENT_POSITION.setStorageAddress(address(_agreement));
emit AgreementSet(_agreement);
}

/**
* @dev Tell the linked Agreement
* @return Agreement
*/
function getAgreement() external view returns (IAgreement) {
return _getAgreement();
}

/**
* @dev Internal implementation of the `onDisputableActionChallenged` hook
* @param _disputableActionId Identifier of the action to be challenged
* @param _challengeId Identifier of the challenge in the context of the Agreement
* @param _challenger Address that submitted the challenge
*/
function _onDisputableActionChallenged(uint256 _disputableActionId, uint256 _challengeId, address _challenger) internal;

/**
* @dev Internal implementation of the `onDisputableActionRejected` hook
* @param _disputableActionId Identifier of the action to be rejected
*/
function _onDisputableActionRejected(uint256 _disputableActionId) internal;

/**
* @dev Internal implementation of the `onDisputableActionAllowed` hook
* @param _disputableActionId Identifier of the action to be allowed
*/
function _onDisputableActionAllowed(uint256 _disputableActionId) internal;

/**
* @dev Internal implementation of the `onDisputableActionVoided` hook
* @param _disputableActionId Identifier of the action to be voided
*/
function _onDisputableActionVoided(uint256 _disputableActionId) internal;

/**
* @dev Create a new action in the Agreement
* @param _disputableActionId Identifier of the action in the context of the Disputable
* @param _context Link to human-readable context for the given action
* @param _submitter Address that submitted the action
* @return Unique identifier for the created action in the context of the Agreement
*/
function _newAgreementAction(uint256 _disputableActionId, bytes _context, address _submitter) internal returns (uint256) {
IAgreement agreement = _ensureAgreement();
return agreement.newAction(_disputableActionId, _context, _submitter);
}

/**
* @dev Close action in the Agreement
* @param _actionId Identifier of the action in the context of the Agreement
*/
function _closeAgreementAction(uint256 _actionId) internal {
IAgreement agreement = _ensureAgreement();
agreement.closeAction(_actionId);
}

/**
* @dev Tell the linked Agreement
* @return Agreement
*/
function _getAgreement() internal view returns (IAgreement) {
return IAgreement(AGREEMENT_POSITION.getStorageAddress());
}

/**
* @dev Tell the linked Agreement or revert if it has not been set
* @return Agreement
*/
function _ensureAgreement() internal view returns (IAgreement) {
IAgreement agreement = _getAgreement();
require(agreement != IAgreement(0), ERROR_AGREEMENT_STATE_INVALID);
return agreement;
}
}
110 changes: 110 additions & 0 deletions contracts/apps/disputable/IAgreement.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* SPDX-License-Identifier: MIT
*/

pragma solidity ^0.4.24;

import "../../acl/IACLOracle.sol";
import "../../lib/token/ERC20.sol";
import "../../lib/arbitration/IArbitrable.sol";
import "../../lib/arbitration/IAragonAppFeesCashier.sol";


contract IAgreement is IArbitrable, IACLOracle {

event Signed(address indexed signer, uint256 settingId);
event SettingChanged(uint256 settingId);
event DisputableAppActivated(address indexed disputable);
event DisputableAppDeactivated(address indexed disputable);
event CollateralRequirementChanged(address indexed disputable, uint256 collateralRequirementId);
event ActionSubmitted(uint256 indexed actionId, address indexed disputable);
event ActionClosed(uint256 indexed actionId);
event ActionChallenged(uint256 indexed actionId, uint256 indexed challengeId);
event ActionSettled(uint256 indexed actionId, uint256 indexed challengeId);
event ActionDisputed(uint256 indexed actionId, uint256 indexed challengeId);
event ActionAccepted(uint256 indexed actionId, uint256 indexed challengeId);
event ActionVoided(uint256 indexed actionId, uint256 indexed challengeId);
event ActionRejected(uint256 indexed actionId, uint256 indexed challengeId);

enum ChallengeState {
Waiting,
Settled,
Disputed,
Rejected,
Accepted,
Voided
}

function sign() external;

function activate(
address _disputable,
ERC20 _collateralToken,
uint256 _actionAmount,
uint256 _challengeAmount,
uint64 _challengeDuration
)
external;

function deactivate(address _disputable) external;

function newAction(uint256 _disputableActionId, bytes _context, address _submitter) external returns (uint256);

function closeAction(uint256 _actionId) external;

function challengeAction(uint256 _actionId, uint256 _settlementOffer, bool _finishedSubmittingEvidence, bytes _context) external;

function settleAction(uint256 _actionId) external;

function disputeAction(uint256 _actionId, bool _finishedSubmittingEvidence) external;

function getSigner(address _signer) external view returns (uint256 lastSettingIdSigned, bool mustSign);

function getCurrentSettingId() external view returns (uint256);

function getSetting(uint256 _settingId) external view
returns (
IArbitrator arbitrator,
IAragonAppFeesCashier aragonAppFeesCashier,
string title,
bytes content
);

function getDisputableInfo(address _disputable) external view returns (bool registered, uint256 currentCollateralRequirementId);

function getCollateralRequirement(address _disputable, uint256 _collateralId) external view
returns (
ERC20 collateralToken,
uint256 actionAmount,
uint256 challengeAmount,
uint64 challengeDuration
);

function getAction(uint256 _actionId) external view
returns (
address disputable,
uint256 disputableActionId,
uint256 collateralRequirementId,
uint256 settingId,
address submitter,
bool closed,
bytes context,
uint256 currentChallengeId
);

function getChallenge(uint256 _challengeId) external view
returns (
uint256 actionId,
address challenger,
uint64 endDate,
bytes context,
uint256 settlementOffer,
uint256 arbitratorFeeAmount,
ERC20 arbitratorFeeToken,
ChallengeState state,
bool submitterFinishedEvidence,
bool challengerFinishedEvidence,
uint256 disputeId,
uint256 ruling
);
}
44 changes: 44 additions & 0 deletions contracts/apps/disputable/IDisputable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* SPDX-License-Identifier: MIT
*/

pragma solidity ^0.4.24;

import "./IAgreement.sol";
import "../../lib/token/ERC20.sol";
import "../../lib/standards/ERC165.sol";


contract IDisputable is ERC165 {
bytes4 internal constant ERC165_INTERFACE_ID = bytes4(0x01ffc9a7);
bytes4 internal constant DISPUTABLE_INTERFACE_ID = bytes4(0x737c65f9);

event AgreementSet(IAgreement indexed agreement);

function setAgreement(IAgreement _agreement) external;

function onDisputableActionChallenged(uint256 _disputableActionId, uint256 _challengeId, address _challenger) external;

function onDisputableActionAllowed(uint256 _disputableActionId) external;

function onDisputableActionRejected(uint256 _disputableActionId) external;

function onDisputableActionVoided(uint256 _disputableActionId) external;

function getAgreement() external view returns (IAgreement);

function canChallenge(uint256 _disputableActionId) external view returns (bool);

function canClose(uint256 _disputableActionId) external view returns (bool);

/**
* @dev Query if a contract implements a certain interface
* @param _interfaceId The interface identifier being queried, as specified in ERC-165
* @return True if the contract implements the requested interface and if its not 0xffffffff, false otherwise
*/
function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {
return _interfaceId == DISPUTABLE_INTERFACE_ID || _interfaceId == ERC165_INTERFACE_ID;
}

function appId() public view returns (bytes32);
}
17 changes: 17 additions & 0 deletions contracts/lib/arbitration/IAragonAppFeesCashier.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
pragma solidity ^0.4.24;

import "../token/ERC20.sol";


interface IAragonAppFeesCashier {
event AppFeeSet(bytes32 indexed appId, ERC20 token, uint256 amount);
event AppFeeUnset(bytes32 indexed appId);
event AppFeePaid(address indexed by, bytes32 appId, bytes data);

function setAppFee(bytes32 _appId, ERC20 _token, uint256 _amount) external;
function setAppFees(bytes32[] _appIds, ERC20[] _tokens, uint256[] _amounts) external;
function unsetAppFee(bytes32 _appId) external;
function unsetAppFees(bytes32[] _appIds) external;
function payAppFees(bytes32 _appId, bytes _data) external;
function getAppFee(bytes32 _appId) external view returns (ERC20, uint256);
}
Loading

0 comments on commit f8a69d8

Please sign in to comment.