# Dispute resolver

{% hint style="info" %}
The dispute resolver entity MUST be created before any dispute resolver actions can be performed.
{% endhint %}

Dispute resolvers decide the dispute outcome when the buyer and seller cannot do it mutually. The dispute resolver is a complex role with admin, assistant and treasury. Initially, all roles must be the same Ethereum address; however, the admin can later change them to other addresses.

Dispute resolvers decide in which tokens they are willing to accept the fee and what the amount is.

Dispute resolvers can set a list of allowed sellers, i.e. the seller ID for which they are willing to do the dispute resolution.

Dispute resolver's funds management is described in [deposit-and-withdraw](https://docs.bosonprotocol.io/using-the-protocol/dacp-tools/finances/deposit-and-withdraw "mention").

### TypeScript SDK

{% tabs fullWidth="true" %}
{% tab title="Create dispute resolver" %}
Creates a new dispute resolver&#x20;

```typescript
const drAddress = signerWallet.address;

await coreSDK.createDisputeResolver({
  assistant: drAddress,
  admin: drAddress,
  treasury: drAddress,
  escalationResponsePeriodInMS: 10 * 24 * 60 * 60 * 1000, // 10 days
  fees: [
    {
    tokenAddress: "0x0000000000000000000000000000000000000000",
    tokenName: "ETH",
    feeAmount: parseEther("0.001")
    },
    {
    tokenAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
    tokenName: "USDC",
    feeAmount: "10000000000"
    }],
  metadataUri: "http://metadata.uri",
});
```

{% endtab %}

{% tab title="Update dispute resolver" %}
Updates an existing dispute resolver.&#x20;

```typescript
const newAssistantWallet = Wallet.createRandom(ethereumProvider);
const disputeResolverId = "12";
const disputeResolver = await coreSDK.getDisputeResolverById(disputeResolverId);

// Start the update with the dispute resolver's wallet
await drCoreSDK.updateDisputeResolver({
   disputeResolverId,
   {
   assistant: newAssistantWallet.address,
   metadataUri: "ipfs://changed",
   escalationResponsePeriodInMS: 123_000
   }
);

// Finalize the update with the assistant's wallet 
const assistantCoreSDK = CoreSDK.fromDefaultConfig({
   envName,
   configId,
   web3Lib: new EthersAdapter(provider, newAssistantWallet),
});

await assistantCoreSDK.optInToDisputeResolverUpdate({
   id: disputeResolverId,
   fieldsToUpdate: {assistant: true}
})
```

{% endtab %}

{% tab title="Manage dispute resolver fees" %}

#### Add supported fee tokens

```typescript
const disputeResolverId = "12";

await drCoreSDK.addFeesToDisputeResolver(
    disputeResolverId,
    {
    tokenAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
    tokenName: "USDC",
    feeAmount: "10000000000"
    }
);
```

#### Remove supported fee tokens

```typescript
const disputeResolverId = "12";

await drCoreSDK.removeFeesFromDisputeResolver(
    disputeResolverId,
    {
    tokenAddress: "0x0000000000000000000000000000000000000000",
    tokenName: "ETH",
    feeAmount: parseEther("0.001")
    }
);
```

{% endtab %}

{% tab title="Manage allowlisted sellers" %}
Add and remove sellers from the dispute resolver's allowlist.

#### Add sellers to the allowlist

```typescript
const disputeResolverId = "12";
const sellerId1 = "153";
const sellerId2 = "2";

await drCoreSDK.addSellersToDisputeResolverAllowList(
    disputeResolverId,
    [sellerId1, sellerId2]
);
```

#### Remove sellers from the allowlist

```typescript
const disputeResolverId = "12";
const sellerId1 = "153";
const sellerId2 = "2";

await drCoreSDK.removeSellersFromDisputeResolverAllowList(
    disputeResolverId,
    [sellerId1, sellerId2]
);
```

{% endtab %}
{% endtabs %}

### Solidity

{% tabs fullWidth="true" %}
{% tab title="Create dispute resolver" %}
Creates a new dispute resolver&#x20;

```solidity
IBosonAccountHandler bosonProtocol = IBosonAccountHandler(_bosonProtocolAddress);

BosonTypes.DisputeResolver memory disputeResolver = BosonTypes.DisputeResolver({
    id: 0, // will be ignored and auto-assigned
    escalationResponsePeriod: 604800, // 1 week in seconds
    assistant: assistantAddress,
    admin: adminAddress,
    clerk: address(0), // deprecated, always zero
    treasury: payable(treasuryAddress),
    metadataUri: "https://ipfs.io/ipfs/dispute-resolver-metadata",
    active: true
});

// Define supported token fees
BosonTypes.DisputeResolverFee[] memory disputeResolverFees = new BosonTypes.DisputeResolverFee[](2);
disputeResolverFees[0] = BosonTypes.DisputeResolverFee({
    tokenAddress: address(0), // native token
    tokenName: "ETH",
    feeAmount: 1e17 // 0.1 ETH
});
disputeResolverFees[1] = BosonTypes.DisputeResolverFee({
    tokenAddress: usdcTokenAddress,
    tokenName: "USDC", 
    feeAmount: 50e6 // 50 USDC (6 decimals)
});

// Define allowed sellers (empty array means no restrictions)
uint256[] memory sellerAllowList = new uint256[](0);

bosonProtocol.createDisputeResolver(disputeResolver, disputeResolverFees, sellerAllowList);
```

{% endtab %}

{% tab title="Update dispute resolver" %}
Updates an existing dispute resolver.&#x20;

{% hint style="info" %}
Changes to admin/assistant require opt-in from the new addresses.
{% endhint %}

```solidity
IBosonAccountHandler bosonProtocol = IBosonAccountHandler(_bosonProtocolAddress);

BosonTypes.DisputeResolver memory disputeResolver = BosonTypes.DisputeResolver({
    id: 1, // existing dispute resolver ID
    escalationResponsePeriod: 1209600, // 2 weeks in seconds
    assistant: newAssistantAddress,
    admin: newAdminAddress,
    clerk: address(0), // deprecated, always zero
    treasury: payable(newTreasuryAddress),
    metadataUri: "https://ipfs.io/ipfs/updated-dispute-resolver-metadata",
    active: true // active flag from storage will be used
});

bosonProtocol.updateDisputeResolver(disputeResolver);

// For admin/assistant updates, new addresses must opt in:
bosonProtocol.optInToDisputeResolverUpdate(disputeResolverId, fieldsToUpdate);
```

{% endtab %}

{% tab title="Manage dispute resolver fees" %}
Add and remove supported fee tokens.

```solidity
IBosonAccountHandler bosonProtocol = IBosonAccountHandler(_bosonProtocolAddress);
uint256 disputeResolverId = 1;

// Add new fee tokens
BosonTypes.DisputeResolverFee[] memory newFees = new BosonTypes.DisputeResolverFee[](1);
newFees[0] = BosonTypes.DisputeResolverFee({
    tokenAddress: daiTokenAddress,
    tokenName: "DAI",
    feeAmount: 25e18 // 25 DAI (18 decimals)
});

bosonProtocol.addFeesToDisputeResolver(disputeResolverId, newFees);

// Remove fee tokens
address[] memory tokenAddressesToRemove = new address[](1);
tokenAddressesToRemove[0] = usdcTokenAddress;

bosonProtocol.removeFeesFromDisputeResolver(disputeResolverId, tokenAddressesToRemove);
```

{% endtab %}

{% tab title="Manage allowlisted sellers" %}
Add and remove sellers from the dispute resolver's allowlist.

```solidity
IBosonAccountHandler bosonProtocol = IBosonAccountHandler(_bosonProtocolAddress);
uint256 disputeResolverId = 1;

// Add sellers to allowlist
uint256[] memory sellersToAdd = new uint256[](2);
sellersToAdd[0] = 1;
sellersToAdd[1] = 2;

bosonProtocol.addSellersToAllowList(disputeResolverId, sellersToAdd);

// Remove sellers from allowlist
uint256[] memory sellersToRemove = new uint256[](1);
sellersToRemove[0] = 1;

bosonProtocol.removeSellersFromAllowList(disputeResolverId, sellersToRemove);
```

{% endtab %}
{% endtabs %}
