Skip to content

Commit 9be56a7

Browse files
authored
Merge pull request #1 from lidofinance/feature/add-ssv-fee-factory
feat: ssv fee
2 parents 6cd4b09 + ec60b92 commit 9be56a7

7 files changed

Lines changed: 37 additions & 23 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@
1616
},
1717
"devDependencies": {
1818
"esbuild": "^0.19.8"
19-
}
19+
},
20+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
2021
}

public/index.html

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ <h1>0x split contract</h1>
5252
</label>
5353
</div>
5454
</div>
55-
<div class="form-row form-row-cluster-type form-row-hidden">
55+
<div class="form-row form-row-wrapper-contract-type form-row-hidden">
5656
<div class="form-label">
57-
<label for="cluster-type-super-cluster">Cluster type</label>
57+
<label for="wrapper-contract-type">Wrapper charges</label>
5858
</div>
5959
<div class="form-input">
60-
<select name="cluster-type" id="cluster-type-super-cluster">
61-
<option value="ssv">SSV</option>
62-
<option value="obol">Obol</option>
60+
<select name="wrapper-contract-type" id="wrapper-contract-type">
61+
<option value="wrapperWithFee">1% fee to DVT provider</option>
62+
<option value="wrapperWithoutFee">no fee</option>
6363
</select>
6464
</div>
6565
</div>
@@ -85,7 +85,8 @@ <h1>Wrapper contract <cite>(cluster reward address)<cite>
8585
</div>
8686
<div class="form-input">
8787
<select name="cluster-type" id="cluster-type">
88-
<option value="ssv">SSV</option>
88+
<option value="ssvWithFee">SSV with fee</option>
89+
<option value="ssvWithoutFee">SSV without fee</option>
8990
<option value="obol">Obol</option>
9091
</select>
9192
</div>

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ flowchart LR;
3232

3333
The UI allows deploying 2 contracts from factories:
3434

35-
**Split Сontract**. A contract that distributes rewards to participants. It uses the 0xSplit factory [0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE](https://etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE) for contract deployment.
35+
**Split Contract**. A contract that distributes rewards to participants. It uses the 0xSplit factory [0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE](https://etherscan.io/address/0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE) for contract deployment.
3636

3737
**Wrapper Contract**. The contract that is specified as the `rewardAddress` of a node operator. Wraps `stETH` rewards to `wstETH` and sends it to the split contract.
3838

src/constants.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ export const contracts = {
66
wrapperFactory: {
77
1: {
88
obol: '0xA9d94139A310150Ca1163b5E23f3E1dbb7D9E2A6',
9-
ssv: '0x3df147bd18854bfa03291034666469237504d4ca',
9+
ssvWithoutFee: '0x3df147bd18854bfa03291034666469237504d4ca',
10+
ssvWithFee: '0x2bc222eda59056d7049f3746083c18550fec4e7f',
1011
},
1112
17000: {
1213
obol: '0x934ec6b68ce7cc3b3e6106c686b5ad808ed26449',
13-
ssv: '0xB7f465f1bd6B2f8DAbA3FcA36c5F5E49E0812F37',
14+
ssvWithoutFee: '0xB7f465f1bd6B2f8DAbA3FcA36c5F5E49E0812F37',
15+
ssvWithFee: 'not_supported',
1416
},
1517
},
1618
treasury: {
@@ -19,7 +21,7 @@ export const contracts = {
1921
},
2022
};
2123

22-
export const treasuryShareByProvider = {
23-
obol: 285714,
24-
ssv: 250000,
24+
export const treasuryShareByType = {
25+
wrapperWithoutFee: 250000,
26+
wrapperWithFee: 285714,
2527
};

src/elements.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ export const splitAddressElement = document.getElementById('split-address') as H
33
export const clusterAddressesElement = document.getElementById('cluster-addresses') as HTMLInputElement;
44
export const clusterIsSuperClusterElement = document.getElementById('cluster-is-super-cluster') as HTMLInputElement;
55

6-
export const superClusterTypeElement = document.getElementById('cluster-type-super-cluster') as HTMLSelectElement;
7-
export const clusterRowClusterType = document.getElementsByClassName('form-row-cluster-type')[0] as HTMLDivElement;
6+
export const wrapperContractTypeElement = document.getElementById('wrapper-contract-type') as HTMLSelectElement;
7+
export const wrapperContractTypeRowElement = document.getElementsByClassName(
8+
'form-row-wrapper-contract-type',
9+
)[0] as HTMLDivElement;
810

911
export const clusterFormWrapperElement = document.getElementById('cluster-form-wrapper') as HTMLFormElement;
1012
export const clusterFormSplitElement = document.getElementById('cluster-form-split') as HTMLFormElement;

src/form-split.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
clusterAddressesElement,
1515
splitAddressElement,
1616
clusterIsSuperClusterElement,
17-
clusterRowClusterType,
17+
wrapperContractTypeRowElement,
1818
} from './elements';
1919
import './gnosis-owners';
2020

@@ -79,8 +79,8 @@ const handleSubmitSplit = (event) => {
7979
clusterFormSplitElement.addEventListener('submit', handleSubmitSplit);
8080
clusterIsSuperClusterElement.addEventListener('change', () => {
8181
if (clusterIsSuperClusterElement.checked) {
82-
clusterRowClusterType.classList.remove('form-row-hidden');
82+
wrapperContractTypeRowElement.classList.remove('form-row-hidden');
8383
} else {
84-
clusterRowClusterType.classList.add('form-row-hidden');
84+
wrapperContractTypeRowElement.classList.add('form-row-hidden');
8585
}
8686
});

src/utils.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { BrowserProvider, Eip1193Provider, JsonRpcSigner, isAddress } from 'ethers';
22
import { modal } from './modal';
3-
import { contracts, treasuryShareByProvider } from './constants';
3+
import { contracts, treasuryShareByType } from './constants';
44
import { Contract } from 'ethers';
5-
import { superClusterTypeElement } from './elements';
5+
import { wrapperContractTypeElement } from './elements';
66

77
export const distributeEvenly = (total: number, participants: number): number[] => {
88
if (participants <= 0) {
@@ -27,10 +27,10 @@ export const calcDistributionForRegularCluster = (accounts: string[], totalShare
2727
};
2828

2929
export const calcDistributionForSuperCluster = (accounts: string[], totalShares: number, chainId: number) => {
30-
const splitType = superClusterTypeElement.value;
31-
validateSplitType(splitType, chainId);
30+
const wrapperContractType = wrapperContractTypeElement.value;
31+
validateWrapperContractType(wrapperContractType);
3232

33-
const treasuryShare = treasuryShareByProvider[splitType];
33+
const treasuryShare = treasuryShareByType[wrapperContractType];
3434
const treasuryAddress = contracts.treasury[chainId];
3535
validateAddress(treasuryAddress);
3636

@@ -114,6 +114,14 @@ export const validateSplitType = (splitType: string, chainId: number) => {
114114
}
115115
};
116116

117+
export const validateWrapperContractType = (wrapperContractType: string) => {
118+
const allowedTypes = new Set(Object.keys(treasuryShareByType));
119+
120+
if (!allowedTypes.has(wrapperContractType)) {
121+
throw new Error(`unknown wrapper contract type "${wrapperContractType}"`);
122+
}
123+
};
124+
117125
export const checkDuplicates = (accounts: string[]) => {
118126
const uniqueAccounts = new Set(accounts.map((address) => address.toLocaleLowerCase()));
119127

0 commit comments

Comments
 (0)