Skip to content

Commit eb13bee

Browse files
entropidelictaturosatiuri-99JuArceMauroToscano
authored
feat: first version of payment system (#449)
Co-authored-by: Santos Rosati <[email protected]> Co-authored-by: Urix <[email protected]> Co-authored-by: JuArce <[email protected]> Co-authored-by: Mauro Toscano <[email protected]>
1 parent 57f43ba commit eb13bee

13 files changed

+186
-38
lines changed

Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
OS := $(shell uname -s)
44

55
CONFIG_FILE?=config-files/config.yaml
6+
AGG_CONFIG_FILE?=config-files/config-aggregator.yaml
67

78
OPERATOR_VERSION=v0.1.6
89

@@ -79,10 +80,9 @@ anvil_start_with_block_time:
7980
@echo "Starting Anvil..."
8081
anvil --load-state contracts/scripts/anvil/state/alignedlayer-deployed-anvil-state.json --block-time 3
8182

82-
# TODO: Allow enviroment variables / different configuration files
8383
aggregator_start:
8484
@echo "Starting Aggregator..."
85-
@go run aggregator/cmd/main.go --config $(CONFIG_FILE) \
85+
@go run aggregator/cmd/main.go --config $(AGG_CONFIG_FILE) \
8686
2>&1 | zap-pretty
8787

8888
aggregator_send_dummy_responses:
@@ -175,10 +175,13 @@ __BATCHER__:
175175

176176
BURST_SIZE=5
177177

178+
batcher_fund_service_manager_balance:
179+
@. ./scripts/fund_batcher_balance_in_aligned_devnet.sh
180+
178181
./batcher/aligned-batcher/.env:
179182
@echo "To start the Batcher ./batcher/aligned-batcher/.env needs to be manually set"; false;
180183

181-
batcher_start: ./batcher/aligned-batcher/.env
184+
batcher_start: ./batcher/aligned-batcher/.env batcher_fund_service_manager_balance
182185
@echo "Starting Batcher..."
183186
@cargo +nightly-2024-04-17 run --manifest-path ./batcher/aligned-batcher/Cargo.toml --release -- --config ./config-files/config.yaml --env-file ./batcher/aligned-batcher/.env
184187

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"pubKey":"E([2836088353050477845347925486470168020568465207212129112527815811278071168630,3160427639470623810295719163087493911148458124491004113623503371537041864385])","crypto":{"cipher":"aes-128-ctr","ciphertext":"208c421cf636f275a42ed905177703c5c33150a405dd9e1b2c7348976f85dcfe","cipherparams":{"iv":"ca35157d20418b2a5f3e08a6e36596fd"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"925af4285f14851f9d83eb7fc2c0ce7ca9f50aa77385519d994ee147f1410607"},"mac":"7e21f43562c4b4cd10b9fe5a149ce66ea17444167f788d6a02a67232d953c4e2"}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"address":"15d34aaf54267db7d7c367839aaf71a00a2c6a65","crypto":{"cipher":"aes-128-ctr","ciphertext":"c649f534580a3f0bf000b221afb0731052f7699298f618e79b2b99fd974c4b16","cipherparams":{"iv":"2fad203c48a2ae479673b17bf110a988"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"72b1c2700f1cccebc468dafecf8de51f19c969389caae7e414c74d699a21c8c4"},"mac":"f093f9d47d3b9aa19be03f2bb9ae96b8c6da7ad0a7c7c0165bdbf84c54c9e26f"},"id":"f2925fb0-b209-4210-af6d-10c44b0e4a84","version":3}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Common variables for all the services
2+
# 'production' only prints info and above. 'development' also prints debug
3+
environment: "production"
4+
aligned_layer_deployment_config_file_path: "./contracts/script/output/devnet/alignedlayer_deployment_output.json"
5+
eigen_layer_deployment_config_file_path: "./contracts/script/output/devnet/eigenlayer_deployment_output.json"
6+
eth_rpc_url: "http://localhost:8545"
7+
eth_ws_url: "ws://localhost:8545"
8+
eigen_metrics_ip_port_address: "localhost:9090"
9+
10+
## ECDSA Configurations
11+
ecdsa:
12+
private_key_store_path: "config-files/anvil.aggregator.ecdsa.key.json"
13+
private_key_store_password: ""
14+
15+
## BLS Configurations
16+
bls:
17+
private_key_store_path: "config-files/anvil.aggregator.bls.key.json"
18+
private_key_store_password: ""
19+
20+
# ## Batcher configurations # batcher:
21+
# block_interval: 3
22+
# batch_size_interval: 10
23+
# max_proof_size: 67108864 # 64 MiB
24+
# max_batch_size: 268435456 # 256 MiB
25+
# eth_ws_reconnects: 99999999999999
26+
# pre_verification_is_enabled: true
27+
28+
## Aggregator Configurations
29+
aggregator:
30+
server_ip_port_address: localhost:8090
31+
bls_public_key_compendium_address: 0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44
32+
avs_service_manager_address: 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690
33+
enable_metrics: true
34+
metrics_ip_port_address: localhost:9091
35+
## Operator Configurations
36+
# operator:
37+
# aggregator_rpc_server_ip_port_address: localhost:8090
38+
# address: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
39+
# earnings_receiver_address: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
40+
# delegation_approver_address: "0x0000000000000000000000000000000000000000"
41+
# staker_opt_out_window_blocks: 0
42+
# metadata_url: "https://yetanotherco.github.io/operator_metadata/metadata.json"
43+
# enable_metrics: true
44+
# metrics_ip_port_address: localhost:9092
45+
# max_batch_size: 268435456 # 256 MiB
46+
# # Operators variables needed for register it in EigenLayer
47+
# el_delegation_manager_address: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9"
48+
# private_key_store_path: config-files/anvil.ecdsa.key.json
49+
# bls_private_key_store_path: config-files/anvil.bls.key.json
50+
# signer_type: local_keystore
51+
# chain_id: 31337

contracts/script/deploy/AlignedLayerDeployer.s.sol

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ contract AlignedLayerDeployer is ExistingDeploymentParser {
108108
* not yet deployed, we give these proxies an empty contract as the initial implementation, to act as if they have no code.
109109
*/
110110
alignedLayerServiceManager = AlignedLayerServiceManager(
111-
address(
111+
payable(
112112
new TransparentUpgradeableProxy(
113113
address(emptyContract),
114114
address(alignedLayerProxyAdmin),
@@ -333,7 +333,7 @@ contract AlignedLayerDeployer is ExistingDeploymentParser {
333333
* not yet deployed, we give these proxies an empty contract as the initial implementation, to act as if they have no code.
334334
*/
335335
alignedLayerServiceManager = AlignedLayerServiceManager(
336-
address(
336+
payable(
337337
new TransparentUpgradeableProxy(
338338
address(emptyContract),
339339
address(alignedLayerProxyAdmin),
@@ -696,7 +696,10 @@ contract AlignedLayerDeployer is ExistingDeploymentParser {
696696
);
697697
}
698698

699-
function _writeOutput(string memory config_data, string memory outputPath) internal {
699+
function _writeOutput(
700+
string memory config_data,
701+
string memory outputPath
702+
) internal {
700703
string memory parent_object = "parent object";
701704

702705
string memory deployed_addresses = "addresses";

contracts/script/upgrade/AlignedLayerUpgrader.s.sol

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,11 @@ contract AlignedLayerUpgrader is Script {
7272

7373
// alignedLayerServiceManager is the proxy
7474
AlignedLayerServiceManager alignedLayerServiceManager = AlignedLayerServiceManager(
75-
stdJson.readAddress(
76-
aligned_deployment_file,
77-
".addresses.alignedLayerServiceManager"
75+
payable(
76+
stdJson.readAddress(
77+
aligned_deployment_file,
78+
".addresses.alignedLayerServiceManager"
79+
)
7880
)
7981
);
8082

contracts/script/upgrade/RegistryCoordinatorUpgrader.s.sol

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ contract RegistryCoordinatorUpgrader is Script {
2525
string memory aligned_deployment_file = vm.readFile(
2626
alignedLayerDeploymentFilePath
2727
);
28-
28+
2929
// Load proxy admin
3030
ProxyAdmin alignedLayerProxyAdmin = ProxyAdmin(
3131
stdJson.readAddress(
@@ -36,19 +36,23 @@ contract RegistryCoordinatorUpgrader is Script {
3636

3737
// Load RegistryCoordinator Proxy
3838
TransparentUpgradeableProxy registryCoordinator = TransparentUpgradeableProxy(
39-
payable(stdJson.readAddress(
40-
aligned_deployment_file,
41-
".addresses.registryCoordinator"
42-
))
43-
);
39+
payable(
40+
stdJson.readAddress(
41+
aligned_deployment_file,
42+
".addresses.registryCoordinator"
43+
)
44+
)
45+
);
4446

4547
// Load RegistryCoordinator dependencies
4648
AlignedLayerServiceManager alignedLayerServiceManager = AlignedLayerServiceManager(
47-
stdJson.readAddress(
48-
aligned_deployment_file,
49-
".addresses.alignedLayerServiceManager"
50-
)
51-
);
49+
payable(
50+
stdJson.readAddress(
51+
aligned_deployment_file,
52+
".addresses.alignedLayerServiceManager"
53+
)
54+
)
55+
);
5256
StakeRegistry stakeRegistry = StakeRegistry(
5357
stdJson.readAddress(
5458
aligned_deployment_file,
@@ -71,20 +75,20 @@ contract RegistryCoordinatorUpgrader is Script {
7175
// Create a new instance of the RegistryCoordinatorImplementation
7276
vm.startBroadcast();
7377
RegistryCoordinator registryCoordinatorImplementation = new RegistryCoordinator(
74-
IServiceManager(address(alignedLayerServiceManager)),
75-
stakeRegistry,
76-
apkRegistry,
77-
indexRegistry
78-
);
78+
IServiceManager(address(alignedLayerServiceManager)),
79+
stakeRegistry,
80+
apkRegistry,
81+
indexRegistry
82+
);
7983
vm.stopBroadcast();
8084

8185
vm.startBroadcast();
8286
alignedLayerProxyAdmin.upgrade(
8387
registryCoordinator,
8488
address(registryCoordinatorImplementation)
85-
);
89+
);
8690
vm.stopBroadcast();
87-
91+
8892
return (
8993
address(registryCoordinator),
9094
address(registryCoordinatorImplementation)

contracts/scripts/anvil/state/alignedlayer-deployed-anvil-state.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

contracts/scripts/anvil/state/eigenlayer-deployed-anvil-state.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,10 @@
288288
},
289289
"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": {
290290
"nonce": 33,
291-
"balance": "0x21e19b29e7e1ee6dc06",
291+
"balance": "0x21e19ba73388f8f654b",
292292
"code": "0x",
293293
"storage": {}
294294
}
295295
},
296-
"best_block_number": "0x13"
296+
"best_block_number": "0x1a"
297297
}

contracts/src/core/AlignedLayerServiceManager.sol

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,17 @@ contract AlignedLayerServiceManager is
6262
"Batch was already submitted"
6363
);
6464

65+
if (msg.value > 0) {
66+
batchersBalances[msg.sender] += msg.value;
67+
}
68+
69+
require(batchersBalances[msg.sender] > 0, "Batcher balance is empty");
70+
6571
BatchState memory batchState;
6672

6773
batchState.taskCreatedBlock = uint32(block.number);
6874
batchState.responded = false;
75+
batchState.batcherAddress = msg.sender;
6976

7077
batchesState[batchMerkleRoot] = batchState;
7178

@@ -77,6 +84,8 @@ contract AlignedLayerServiceManager is
7784
bytes32 batchMerkleRoot,
7885
NonSignerStakesAndSignature memory nonSignerStakesAndSignature
7986
) external {
87+
uint256 initialGasLeft = gasleft();
88+
8089
/* CHECKING SIGNATURES & WHETHER THRESHOLD IS MET OR NOT */
8190

8291
// Note: This is a hacky solidity way to see that the element exists
@@ -91,6 +100,12 @@ contract AlignedLayerServiceManager is
91100
batchesState[batchMerkleRoot].responded == false,
92101
"Batch already responded"
93102
);
103+
104+
require(
105+
batchersBalances[batchesState[batchMerkleRoot].batcherAddress] > 0,
106+
"Batcher has no balance"
107+
);
108+
94109
batchesState[batchMerkleRoot].responded = true;
95110

96111
/* CHECKING SIGNATURES & WHETHER THRESHOLD IS MET OR NOT */
@@ -113,6 +128,24 @@ contract AlignedLayerServiceManager is
113128
);
114129

115130
emit BatchVerified(batchMerkleRoot);
131+
132+
// Calculate estimation of gas used, check that batcher has sufficient funds
133+
// and send transaction cost to aggregator.
134+
uint256 finalGasLeft = gasleft();
135+
136+
// FIXME: should we add 21000 gas from the transfer + some additional for the other steps (~40k gas)?
137+
uint256 txCost = (initialGasLeft - finalGasLeft + 21000) * tx.gasprice;
138+
139+
require(
140+
batchersBalances[batchesState[batchMerkleRoot].batcherAddress] >=
141+
txCost,
142+
"Batcher has not sufficient funds for paying this transaction"
143+
);
144+
145+
batchersBalances[
146+
batchesState[batchMerkleRoot].batcherAddress
147+
] -= txCost;
148+
payable(msg.sender).transfer(txCost);
116149
}
117150

118151
function verifyBatchInclusion(
@@ -149,4 +182,12 @@ contract AlignedLayerServiceManager is
149182
verificationDataBatchIndex
150183
);
151184
}
185+
186+
function balanceOf(address account) public view returns (uint256) {
187+
return batchersBalances[account];
188+
}
189+
190+
receive() external payable {
191+
batchersBalances[msg.sender] += msg.value;
192+
}
152193
}

0 commit comments

Comments
 (0)