This repository has been archived by the owner on Jan 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
GatewayManagerFacet.sol
155 lines (122 loc) · 5.19 KB
/
GatewayManagerFacet.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.19;
import {GatewayActorModifiers} from "../lib/LibGatewayActorStorage.sol";
import {CrossMsg} from "../structs/Checkpoint.sol";
import {Status} from "../enums/Status.sol";
import {FvmAddress} from "../structs/FvmAddress.sol";
import {SubnetID, Subnet} from "../structs/Subnet.sol";
import {Membership} from "../structs/Subnet.sol";
import {AlreadyRegisteredSubnet, CannotReleaseZero, NotEnoughFunds, NotEnoughFundsToRelease, NotEmptySubnetCircSupply, NotRegisteredSubnet} from "../errors/IPCErrors.sol";
import {LibGateway} from "../lib/LibGateway.sol";
import {FvmAddressHelper} from "../lib/FvmAddressHelper.sol";
import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol";
import {CrossMsgHelper} from "../lib/CrossMsgHelper.sol";
import {FilAddress} from "fevmate/utils/FilAddress.sol";
import {ReentrancyGuard} from "../lib/LibReentrancyGuard.sol";
contract GatewayManagerFacet is GatewayActorModifiers, ReentrancyGuard {
using FilAddress for address payable;
using SubnetIDHelper for SubnetID;
using FvmAddressHelper for FvmAddress;
/// @notice register a subnet in the gateway. It is called by a subnet when it reaches the threshold stake
function register() external payable {
if (msg.value < s.minStake) {
revert NotEnoughFunds();
}
SubnetID memory subnetId = s.networkName.createSubnetId(msg.sender);
(bool registered, Subnet storage subnet) = LibGateway.getSubnet(subnetId);
if (registered) {
revert AlreadyRegisteredSubnet();
}
subnet.id = subnetId;
subnet.stake = msg.value;
subnet.status = Status.Active;
subnet.genesisEpoch = block.number;
s.subnetKeys.push(subnetId.toHash());
s.totalSubnets += 1;
}
/// @notice addStake - add collateral for an existing subnet
function addStake() external payable {
if (msg.value <= 0) {
revert NotEnoughFunds();
}
(bool registered, Subnet storage subnet) = LibGateway.getSubnet(msg.sender);
if (!registered) {
revert NotRegisteredSubnet();
}
subnet.stake += msg.value;
if (subnet.status == Status.Inactive) {
if (subnet.stake >= s.minStake) {
subnet.status = Status.Active;
}
}
}
/// @notice release amount for an existing subnet
/// @dev it can be used to release the stake or reward of the validator
/// @notice release collateral for an existing subnet
function releaseStake(uint256 amount) external nonReentrant {
if (amount == 0) {
revert CannotReleaseZero();
}
(bool registered, Subnet storage subnet) = LibGateway.getSubnet(msg.sender);
if (!registered) {
revert NotRegisteredSubnet();
}
if (subnet.stake < amount) {
revert NotEnoughFundsToRelease();
}
subnet.stake -= amount;
if (subnet.stake < s.minStake) {
subnet.status = Status.Inactive;
}
payable(subnet.id.getActor()).sendValue(amount);
}
function releaseRewardForRelayer(uint256 amount) external nonReentrant {
if (amount == 0) {
revert CannotReleaseZero();
}
(bool registered, Subnet storage subnet) = LibGateway.getSubnet(msg.sender);
if (!registered) {
revert NotRegisteredSubnet();
}
payable(subnet.id.getActor()).sendValue(amount);
}
/// @notice kill an existing subnet. It's balance must be empty
function kill() external {
(bool registered, Subnet storage subnet) = LibGateway.getSubnet(msg.sender);
if (!registered) {
revert NotRegisteredSubnet();
}
if (subnet.circSupply > 0) {
revert NotEmptySubnetCircSupply();
}
uint256 stake = subnet.stake;
s.totalSubnets -= 1;
delete s.subnets[subnet.id.toHash()];
payable(msg.sender).sendValue(stake);
}
/// @notice fund - commit a top-down message releasing funds in a child subnet. There is an associated fee that gets distributed to validators in the subnet as well
/// @param subnetId - subnet to fund
/// @param to - the address to send funds to
function fund(SubnetID calldata subnetId, FvmAddress calldata to) external payable {
CrossMsg memory crossMsg = CrossMsgHelper.createFundMsg({
subnet: subnetId,
signer: msg.sender,
to: to,
value: msg.value,
fee: 0 // injecting funds into a subnet should is free
});
// commit top-down message.
LibGateway.commitTopDownMsg(crossMsg);
}
/// @notice release method locks funds in the current subnet and sends a cross message up the hierarchy to the parent gateway to release the funds
function release(FvmAddress calldata to, uint256 fee) external payable validFee(fee) {
CrossMsg memory crossMsg = CrossMsgHelper.createReleaseMsg({
subnet: s.networkName,
signer: msg.sender,
to: to,
value: msg.value - fee,
fee: fee
});
LibGateway.commitBottomUpMsg(crossMsg);
}
}