Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows DR creation without the need for activation by protocol admin #466

Merged
merged 12 commits into from
Nov 17, 2022
1 change: 1 addition & 0 deletions contracts/domain/BosonConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ string constant NO_SUCH_DISPUTE_RESOLVER = "No such dispute resolver";
string constant INVALID_ESCALATION_PERIOD = "Invalid escalation period";
string constant INVALID_AMOUNT_DISPUTE_RESOLVER_FEES = "Dispute resolver fees are not present or exceed maximum dispute resolver fees in a single transaction";
string constant DUPLICATE_DISPUTE_RESOLVER_FEES = "Duplicate dispute resolver fee";
string constant FEE_AMOUNT_NOT_YET_SUPPORTED = "Non-zero dispute resolver fees not yet supported";
string constant DISPUTE_RESOLVER_FEE_NOT_FOUND = "Dispute resolver fee not found";
string constant SELLER_ALREADY_APPROVED = "Seller id is approved already";
string constant SELLER_NOT_APPROVED = "Seller id is not approved";
Expand Down
6 changes: 0 additions & 6 deletions contracts/interfaces/events/IBosonAccountEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,5 @@ interface IBosonAccountEvents {
uint256[] removedSellers,
address indexed executedBy
);
event DisputeResolverActivated(
uint256 indexed disputeResolverId,
BosonTypes.DisputeResolver disputeResolver,
address indexed executedBy
);

event AgentCreated(uint256 indexed agentId, BosonTypes.Agent agent, address indexed executedBy);
}
29 changes: 8 additions & 21 deletions contracts/interfaces/handlers/IBosonAccountHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { IBosonAccountEvents } from "../events/IBosonAccountEvents.sol";
*
* @notice Handles creation, update, retrieval of accounts within the protocol.
*
* The ERC-165 identifier for this interface is: 0xb8667cfd
* The ERC-165 identifier for this interface is: 0x1f891681
*/
interface IBosonAccountHandler is IBosonAccountEvents {
/**
Expand Down Expand Up @@ -54,7 +54,7 @@ interface IBosonAccountHandler is IBosonAccountEvents {
function createBuyer(BosonTypes.Buyer memory _buyer) external;

/**
* @notice Creates a dispute resolver. Dispute resolver must be activated before it can participate in the protocol.
* @notice Creates a dispute resolver.
*
* Emits a DisputeResolverCreated event if successful.
*
Expand All @@ -63,15 +63,16 @@ interface IBosonAccountHandler is IBosonAccountEvents {
* - The dispute resolvers region of protocol is paused
* - Any address is zero address
* - Any address is not unique to this dispute resolver
* - Number of DisputeResolverFee structs in array exceeds max
* - DisputeResolverFee array contains duplicates
* - EscalationResponsePeriod is invalid
* - Number of seller ids in _sellerAllowList array exceeds max
* - Some seller does not exist
* - Some seller id is duplicated
* - DisputeResolver is not active (if active == false)
* - Fee amount is a non-zero value. Protocol doesn't yet support fees for dispute resolvers
*
* @param _disputeResolver - the fully populated struct with dispute resolver id set to 0x0
* @param _disputeResolverFees - array of fees dispute resolver charges per token type. Zero address is native currency. Can be empty.
* @param _disputeResolverFees - list of fees dispute resolver charges per token type. Zero address is native currency. See {BosonTypes.DisputeResolverFee}
* feeAmount will be ignored because protocol doesn't yet support fees yet but DR still needs to provide array of fees to choose supported tokens
* @param _sellerAllowList - list of ids of sellers that can choose this dispute resolver. If empty, there are no restrictions on which seller can chose it.
*/
function createDisputeResolver(
Expand Down Expand Up @@ -234,9 +235,11 @@ interface IBosonAccountHandler is IBosonAccountEvents {
* - Number of DisputeResolverFee structs in array exceeds max
* - Number of DisputeResolverFee structs in array is zero
* - DisputeResolverFee array contains duplicates
* - Fee amount is a non-zero value. Protocol doesn't yet support fees for dispute resolvers
*
* @param _disputeResolverId - id of the dispute resolver
* @param _disputeResolverFees - list of fees dispute resolver charges per token type. Zero address is native currency. See {BosonTypes.DisputeResolverFee}
* feeAmount will be ignored because protocol doesn't yet support fees yet but DR still needs to provide array of fees to choose supported tokens
*/
function addFeesToDisputeResolver(
uint256 _disputeResolverId,
Expand Down Expand Up @@ -298,22 +301,6 @@ interface IBosonAccountHandler is IBosonAccountEvents {
*/
function removeSellersFromAllowList(uint256 _disputeResolverId, uint256[] calldata _sellerAllowList) external;

/**
* @notice Sets the active flag for this dispute resolver to true.
*
* @dev Only callable by the protocol ADMIN role.
*
* Emits a DisputeResolverActivated event if successful.
*
* Reverts if:
* - The dispute resolvers region of protocol is paused
* - Caller does not have the ADMIN role
* - Dispute resolver does not exist
*
* @param _disputeResolverId - id of the dispute resolver
*/
function activateDisputeResolver(uint256 _disputeResolverId) external;

/**
* @notice Gets the details about a seller.
*
Expand Down
59 changes: 18 additions & 41 deletions contracts/protocol/facets/DisputeResolverHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ contract DisputeResolverHandlerFacet is IBosonAccountEvents, ProtocolBase {
}

/**
* @notice Creates a dispute resolver. Dispute resolver must be activated before it can participate in the protocol.
* @notice Creates a dispute resolver.
*
* Emits a DisputeResolverCreated event if successful.
*
Expand All @@ -32,15 +32,16 @@ contract DisputeResolverHandlerFacet is IBosonAccountEvents, ProtocolBase {
* - The dispute resolvers region of protocol is paused
* - Any address is zero address
* - Any address is not unique to this dispute resolver
* - Number of DisputeResolverFee structs in array exceeds max
* - DisputeResolverFee array contains duplicates
* - EscalationResponsePeriod is invalid
* - Number of seller ids in _sellerAllowList array exceeds max
* - Some seller does not exist
* - Some seller id is duplicated
* - DisputeResolver is not active (if active == false)
* - Fee amount is a non-zero value. Protocol doesn't yet support fees for dispute resolvers
*
* @param _disputeResolver - the fully populated struct with dispute resolver id set to 0x0
* @param _disputeResolverFees - array of fees dispute resolver charges per token type. Zero address is native currency. Can be empty.
* @param _disputeResolverFees - list of fees dispute resolver charges per token type. Zero address is native currency. See {BosonTypes.DisputeResolverFee}
* feeAmount will be ignored because protocol doesn't yet support fees yet but DR still needs to provide array of fees to choose supported tokens
* @param _sellerAllowList - list of ids of sellers that can choose this dispute resolver. If empty, there are no restrictions on which seller can chose it.
*/
function createDisputeResolver(
Expand All @@ -60,6 +61,9 @@ contract DisputeResolverHandlerFacet is IBosonAccountEvents, ProtocolBase {
INVALID_ADDRESS
);

// Check active is not set to false
require(_disputeResolver.active, MUST_BE_ACTIVE);

// Scope to avoid stack too deep errors
{
// Get message sender
Expand Down Expand Up @@ -125,20 +129,22 @@ contract DisputeResolverHandlerFacet is IBosonAccountEvents, ProtocolBase {
mapping(address => uint256) storage disputeResolverFeeTokens = lookups.disputeResolverFeeTokenIndex[
_disputeResolver.id
];

for (uint256 i = 0; i < _disputeResolverFees.length; i++) {
require(
disputeResolverFeeTokens[_disputeResolverFees[i].tokenAddress] == 0,
DUPLICATE_DISPUTE_RESOLVER_FEES
);

// Protocol doesn't yet support DR fees
require(_disputeResolverFees[i].feeAmount == 0, FEE_AMOUNT_NOT_YET_SUPPORTED);

disputeResolverFees.push(_disputeResolverFees[i]);

// Set index mapping. Should be index in disputeResolverFees array + 1
disputeResolverFeeTokens[_disputeResolverFees[i].tokenAddress] = disputeResolverFees.length;
}

// Ignore supplied active flag and set to false. Dispute resolver must be activated by protocol.
_disputeResolver.active = false;

storeDisputeResolver(_disputeResolver);
storeSellerAllowList(disputeResolverId, _sellerAllowList);

Expand Down Expand Up @@ -409,9 +415,11 @@ contract DisputeResolverHandlerFacet is IBosonAccountEvents, ProtocolBase {
* - Number of DisputeResolverFee structs in array exceeds max
* - Number of DisputeResolverFee structs in array is zero
* - DisputeResolverFee array contains duplicates
* - Fee amount is a non-zero value. Protocol doesn't yet support fees for dispute resolvers
*
* @param _disputeResolverId - id of the dispute resolver
* @param _disputeResolverFees - list of fees dispute resolver charges per token type. Zero address is native currency. See {BosonTypes.DisputeResolverFee}
* feeAmount will be ignored because protocol doesn't yet support fees yet but DR still needs to provide array of fees to choose supported tokens
*/
function addFeesToDisputeResolver(uint256 _disputeResolverId, DisputeResolverFee[] calldata _disputeResolverFees)
external
Expand Down Expand Up @@ -450,6 +458,9 @@ contract DisputeResolverHandlerFacet is IBosonAccountEvents, ProtocolBase {
lookups.disputeResolverFeeTokenIndex[_disputeResolverId][_disputeResolverFees[i].tokenAddress] == 0,
DUPLICATE_DISPUTE_RESOLVER_FEES
);
// Protocol doesn't yet support DR fees
require(_disputeResolverFees[i].feeAmount == 0, FEE_AMOUNT_NOT_YET_SUPPORTED);

disputeResolverFees.push(_disputeResolverFees[i]);
lookups.disputeResolverFeeTokenIndex[_disputeResolverId][
_disputeResolverFees[i].tokenAddress
Expand Down Expand Up @@ -650,40 +661,6 @@ contract DisputeResolverHandlerFacet is IBosonAccountEvents, ProtocolBase {
emit AllowedSellersRemoved(_disputeResolverId, _sellerAllowList, sender);
}

/**
* @notice Sets the active flag for this dispute resolver to true.
*
* @dev Only callable by the protocol ADMIN role.
*
* Emits a DisputeResolverActivated event if successful.
*
* Reverts if:
* - The dispute resolvers region of protocol is paused
* - Caller does not have the ADMIN role
* - Dispute resolver does not exist
*
* @param _disputeResolverId - id of the dispute resolver
*/
function activateDisputeResolver(uint256 _disputeResolverId)
external
disputeResolversNotPaused
onlyRole(ADMIN)
nonReentrant
{
bool exists;
DisputeResolver storage disputeResolver;

// Check dispute resolver and dispute resolver fees from disputeResolvers and disputeResolverFees mappings
(exists, disputeResolver, ) = fetchDisputeResolver(_disputeResolverId);

// Dispute resolver must already exist
require(exists, NO_SUCH_DISPUTE_RESOLVER);

disputeResolver.active = true;

emit DisputeResolverActivated(_disputeResolverId, disputeResolver, msgSender());
}

/**
* @notice Gets the details about a dispute resolver.
*
Expand Down
4 changes: 2 additions & 2 deletions docs/local-development.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ This deploys all contract on the local node and prints out all the information a
### [Optional] Manage roles
If you want to perform any of the following:
- change any of protocol configuration parameters
- use dispute resolver, which needs to be activated by the admin
- use dispute resolver
- set up other roles, needed for some functionalities of the protocol (e.g. PAUSE, FEE_COLLECTOR)

you need to set up the admin account. To do it
Expand Down Expand Up @@ -111,4 +111,4 @@ To perform the upgrade you then
You can find the examples how to use all functions of the protocol in our test files in folder `test/protocol`.

### Using other npm scripts
We provide some scripts to perform other tasks in this repo (e.g. just building the contracts, testing, sizing etc.). You can find more info about it on separate page [Tasks](tasks.md).
We provide some scripts to perform other tasks in this repo (e.g. just building the contracts, testing, sizing etc.). You can find more info about it on separate page [Tasks](tasks.md).
14 changes: 6 additions & 8 deletions docs/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ It outputs the list of files with errors of two types:
Script will try to automatically fix the wrong interfaces if you run it with
```npm run natspec-interface-id:fix```, however this cannot fix the missing interface ids.

### Create and/or activate dispute resolver
### Create dispute resolver

Script will create and/or activate a dispute resolver
Script will create a dispute resolver

**Arguments**:
- `path`: Required argument with path for a JSON file containing the following
Expand All @@ -148,7 +148,7 @@ Script will create and/or activate a dispute resolver
"clerk": string,
"treasury": string,
"metadataUri": string,
"active": boolean // ignored
"active": boolean
},
"disputeResolverFees": [
{
Expand All @@ -162,19 +162,17 @@ Script will create and/or activate a dispute resolver
}
```
- `network`: Network to run the script
- `activate-only (optional)`: Optional flag to only activate the Dispute Resolver
- `create-only (optional)`: Optional flag to only create the Dispute Resolver


Note about the field `privateKey` in JSON file:
- `privateKey` represents the hex encoded private key that will create a dispute resolver. If it is not specified, the protocol admin account will be used (same account that later activate the dispute resolver and is specified in `.env`).
- If all `operator`, `admin` and `clerk` match the address, corresponding to `privateKey`, dispute resolver is simply created and activated.
- `privateKey` represents the hex encoded private key that will create a dispute resolver. If it is not specified, the protocol admin account will be used (specified in `.env`).
- If all `operator`, `admin` and `clerk` match the address, corresponding to `privateKey`, dispute resolver is simply created.
- If any of `operator`, `admin` or `clerk` differs from the address, corresponding to `privateKey`, dispute resolver is created in two steps. Firstly, a dispute resolver with `operator`, `admin` and `clerk` set to address, corresponding to `privateKey` is created and then in the second step dispute resolver is updated with addresses from JSON file.

Example:

```
npx hardhat create-dispute-resolver --path "path/to/dispute_resolver.json" --network localhost --create-only
npx hardhat create-dispute-resolver --path "path/to/dispute_resolver.json" --network localhost
```


Expand Down
10 changes: 4 additions & 6 deletions hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@ task("estimate-limits", "Estimates the maximum values for limits in protocol con
await estimateLimits();
});

task("create-dispute-resolver", "Creates and activates a dispute resolver")
task("create-dispute-resolver", "Creates a dispute resolver")
.addParam("path", "The path to the dispute resolver json file")
.addFlag("createOnly", "Only create the dispute resolver")
.addFlag("activateOnly", "Only activate the dispute resolver")
.setAction(async ({ path, createOnly, activateOnly }) => {
const { createAndActivateDR } = await lazyImport("./scripts/util/create-and-activate-DR");
await createAndActivateDR(path, createOnly, activateOnly);
.setAction(async ({ path }) => {
const { createDisputeResolver } = await lazyImport("./scripts/util/create-dispute-resolver");
await createDisputeResolver(path);
});

task("verify-suite", "Verify contracts on the block explorer")
Expand Down
1 change: 1 addition & 0 deletions scripts/config/revert-reasons.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ exports.RevertReasons = {
"Dispute resolver fees are not present or exceed maximum dispute resolver fees in a single transaction",
DUPLICATE_DISPUTE_RESOLVER_FEES: "Duplicate dispute resolver fee",
DISPUTE_RESOLVER_FEE_NOT_FOUND: "Dispute resolver fee not found",
FEE_AMOUNT_NOT_YET_SUPPORTED: "Non-zero dispute resolver fees not yet supported",
INVALID_AUTH_TOKEN_TYPE: "Invalid AuthTokenType",
ADMIN_OR_AUTH_TOKEN: "An admin address or an auth token is required",
AUTH_TOKEN_MUST_BE_UNIQUE: "Auth token cannot be assigned to another entity of the same type",
Expand Down
Loading