diff --git a/contracts/.storage-layouts/GatewayActorModifiers.json b/contracts/.storage-layouts/GatewayActorModifiers.json index abbab27cef..c1987575a4 100644 --- a/contracts/.storage-layouts/GatewayActorModifiers.json +++ b/contracts/.storage-layouts/GatewayActorModifiers.json @@ -1,12 +1,12 @@ { "storage": [ { - "astId": 11134, + "astId": 11979, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "s", "offset": 0, "slot": "0", - "type": "t_struct(GatewayActorStorage)11120_storage" + "type": "t_struct(GatewayActorStorage)11965_storage" } ], "types": { @@ -27,14 +27,14 @@ "label": "bytes32[]", "numberOfBytes": "32" }, - "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage": { - "base": "t_struct(IpcEnvelope)18187_storage", + "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage": { + "base": "t_struct(IpcEnvelope)18702_storage", "encoding": "dynamic_array", "label": "struct IpcEnvelope[]", "numberOfBytes": "32" }, - "t_array(t_struct(Validator)18451_storage)dyn_storage": { - "base": "t_struct(Validator)18451_storage", + "t_array(t_struct(Validator)18966_storage)dyn_storage": { + "base": "t_struct(Validator)18966_storage", "encoding": "dynamic_array", "label": "struct Validator[]", "numberOfBytes": "32" @@ -54,22 +54,22 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_enum(IpcMsgKind)18164": { + "t_enum(IpcMsgKind)18679": { "encoding": "inplace", "label": "enum IpcMsgKind", "numberOfBytes": "1" }, - "t_enum(PermissionMode)18397": { + "t_enum(PermissionMode)18912": { "encoding": "inplace", "label": "enum PermissionMode", "numberOfBytes": "1" }, - "t_enum(QuorumObjKind)18233": { + "t_enum(QuorumObjKind)18748": { "encoding": "inplace", "label": "enum QuorumObjKind", "numberOfBytes": "1" }, - "t_enum(StakingOperation)18320": { + "t_enum(StakingOperation)18835": { "encoding": "inplace", "label": "enum StakingOperation", "numberOfBytes": "1" @@ -81,12 +81,12 @@ "numberOfBytes": "32", "value": "t_bytes_storage" }, - "t_mapping(t_address,t_struct(ValidatorInfo)18392_storage)": { + "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ValidatorInfo)", "numberOfBytes": "32", - "value": "t_struct(ValidatorInfo)18392_storage" + "value": "t_struct(ValidatorInfo)18907_storage" }, "t_mapping(t_address,t_uint16)": { "encoding": "mapping", @@ -95,19 +95,19 @@ "numberOfBytes": "32", "value": "t_uint16" }, - "t_mapping(t_bytes32,t_struct(IpcEnvelope)18187_storage)": { + "t_mapping(t_bytes32,t_struct(IpcEnvelope)18702_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct IpcEnvelope)", "numberOfBytes": "32", - "value": "t_struct(IpcEnvelope)18187_storage" + "value": "t_struct(IpcEnvelope)18702_storage" }, - "t_mapping(t_bytes32,t_struct(Subnet)18314_storage)": { + "t_mapping(t_bytes32,t_struct(Subnet)18829_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct Subnet)", "numberOfBytes": "32", - "value": "t_struct(Subnet)18314_storage" + "value": "t_struct(Subnet)18829_storage" }, "t_mapping(t_bytes32,t_uint256)": { "encoding": "mapping", @@ -137,40 +137,40 @@ "numberOfBytes": "32", "value": "t_struct(AddressSet)3459_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18139_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpCheckpoint)", "numberOfBytes": "32", - "value": "t_struct(BottomUpCheckpoint)18139_storage" + "value": "t_struct(BottomUpCheckpoint)18654_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18153_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18668_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpMsgBatch)", "numberOfBytes": "32", - "value": "t_struct(BottomUpMsgBatch)18153_storage" + "value": "t_struct(BottomUpMsgBatch)18668_storage" }, - "t_mapping(t_uint256,t_struct(ParentFinality)18119_storage)": { + "t_mapping(t_uint256,t_struct(ParentFinality)18634_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct ParentFinality)", "numberOfBytes": "32", - "value": "t_struct(ParentFinality)18119_storage" + "value": "t_struct(ParentFinality)18634_storage" }, - "t_mapping(t_uint256,t_struct(QuorumInfo)18250_storage)": { + "t_mapping(t_uint256,t_struct(QuorumInfo)18765_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct QuorumInfo)", "numberOfBytes": "32", - "value": "t_struct(QuorumInfo)18250_storage" + "value": "t_struct(QuorumInfo)18765_storage" }, - "t_mapping(t_uint64,t_struct(StakingChange)18329_storage)": { + "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)": { "encoding": "mapping", "key": "t_uint64", "label": "mapping(uint64 => struct StakingChange)", "numberOfBytes": "32", - "value": "t_struct(StakingChange)18329_storage" + "value": "t_struct(StakingChange)18844_storage" }, "t_struct(AddressSet)3459_storage": { "encoding": "inplace", @@ -187,20 +187,20 @@ ], "numberOfBytes": "64" }, - "t_struct(BottomUpCheckpoint)18139_storage": { + "t_struct(BottomUpCheckpoint)18654_storage": { "encoding": "inplace", "label": "struct BottomUpCheckpoint", "members": [ { - "astId": 18124, + "astId": 18639, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18127, + "astId": 18642, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "blockHeight", "offset": 0, @@ -208,7 +208,7 @@ "type": "t_uint256" }, { - "astId": 18130, + "astId": 18645, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "blockHash", "offset": 0, @@ -216,7 +216,7 @@ "type": "t_bytes32" }, { - "astId": 18133, + "astId": 18648, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "nextConfigurationNumber", "offset": 0, @@ -224,30 +224,30 @@ "type": "t_uint64" }, { - "astId": 18138, + "astId": 18653, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "msgs", "offset": 0, "slot": "5", - "type": "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" } ], "numberOfBytes": "192" }, - "t_struct(BottomUpMsgBatch)18153_storage": { + "t_struct(BottomUpMsgBatch)18668_storage": { "encoding": "inplace", "label": "struct BottomUpMsgBatch", "members": [ { - "astId": 18144, + "astId": 18659, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18147, + "astId": 18662, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "blockHeight", "offset": 0, @@ -255,12 +255,12 @@ "type": "t_uint256" }, { - "astId": 18152, + "astId": 18667, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "msgs", "offset": 0, "slot": "3", - "type": "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" } ], "numberOfBytes": "128" @@ -280,12 +280,12 @@ ], "numberOfBytes": "64" }, - "t_struct(FvmAddress)18218_storage": { + "t_struct(FvmAddress)18733_storage": { "encoding": "inplace", "label": "struct FvmAddress", "members": [ { - "astId": 18215, + "astId": 18730, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "addrType", "offset": 0, @@ -293,7 +293,7 @@ "type": "t_uint8" }, { - "astId": 18217, + "astId": 18732, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "payload", "offset": 0, @@ -303,12 +303,12 @@ ], "numberOfBytes": "64" }, - "t_struct(GatewayActorStorage)11120_storage": { + "t_struct(GatewayActorStorage)11965_storage": { "encoding": "inplace", "label": "struct GatewayActorStorage", "members": [ { - "astId": 11032, + "astId": 11877, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "latestParentHeight", "offset": 0, @@ -316,7 +316,7 @@ "type": "t_uint256" }, { - "astId": 11035, + "astId": 11880, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpCheckPeriod", "offset": 0, @@ -324,7 +324,7 @@ "type": "t_uint256" }, { - "astId": 11038, + "astId": 11883, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpMsgBatchPeriod", "offset": 0, @@ -332,7 +332,7 @@ "type": "t_uint256" }, { - "astId": 11041, + "astId": 11886, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpNonce", "offset": 0, @@ -340,7 +340,7 @@ "type": "t_uint64" }, { - "astId": 11044, + "astId": 11889, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "appliedTopDownNonce", "offset": 8, @@ -348,7 +348,7 @@ "type": "t_uint64" }, { - "astId": 11047, + "astId": 11892, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "totalSubnets", "offset": 16, @@ -356,7 +356,7 @@ "type": "t_uint64" }, { - "astId": 11050, + "astId": 11895, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "maxMsgsPerBottomUpBatch", "offset": 24, @@ -364,7 +364,7 @@ "type": "t_uint64" }, { - "astId": 11053, + "astId": 11898, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "majorityPercentage", "offset": 0, @@ -372,7 +372,7 @@ "type": "t_uint8" }, { - "astId": 11056, + "astId": 11901, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "commitSha", "offset": 0, @@ -380,7 +380,7 @@ "type": "t_bytes32" }, { - "astId": 11059, + "astId": 11904, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "maxTreeDepth", "offset": 0, @@ -388,7 +388,7 @@ "type": "t_uint8" }, { - "astId": 11062, + "astId": 11907, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "generalPurposeCrossMsg", "offset": 1, @@ -396,7 +396,7 @@ "type": "t_bool" }, { - "astId": 11065, + "astId": 11910, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "multiLevelCrossMsg", "offset": 2, @@ -404,87 +404,87 @@ "type": "t_bool" }, { - "astId": 11069, + "astId": 11914, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "currentMembership", "offset": 0, "slot": "7", - "type": "t_struct(Membership)18459_storage" + "type": "t_struct(Membership)18974_storage" }, { - "astId": 11073, + "astId": 11918, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "lastMembership", "offset": 0, "slot": "9", - "type": "t_struct(Membership)18459_storage" + "type": "t_struct(Membership)18974_storage" }, { - "astId": 11077, + "astId": 11922, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "checkpointQuorumMap", "offset": 0, "slot": "11", - "type": "t_struct(QuorumMap)18282_storage" + "type": "t_struct(QuorumMap)18797_storage" }, { - "astId": 11081, + "astId": 11926, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "networkName", "offset": 0, "slot": "18", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 11085, + "astId": 11930, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validatorsTracker", "offset": 0, "slot": "20", - "type": "t_struct(ParentValidatorsTracker)18435_storage" + "type": "t_struct(ParentValidatorsTracker)18950_storage" }, { - "astId": 11091, + "astId": 11936, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnets", "offset": 0, "slot": "31", - "type": "t_mapping(t_bytes32,t_struct(Subnet)18314_storage)" + "type": "t_mapping(t_bytes32,t_struct(Subnet)18829_storage)" }, { - "astId": 11097, + "astId": 11942, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "finalitiesMap", "offset": 0, "slot": "32", - "type": "t_mapping(t_uint256,t_struct(ParentFinality)18119_storage)" + "type": "t_mapping(t_uint256,t_struct(ParentFinality)18634_storage)" }, { - "astId": 11103, + "astId": 11948, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "postbox", "offset": 0, "slot": "33", - "type": "t_mapping(t_bytes32,t_struct(IpcEnvelope)18187_storage)" + "type": "t_mapping(t_bytes32,t_struct(IpcEnvelope)18702_storage)" }, { - "astId": 11109, + "astId": 11954, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpCheckpoints", "offset": 0, "slot": "34", - "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18139_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)" }, { - "astId": 11115, + "astId": 11960, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "bottomUpMsgBatches", "offset": 0, "slot": "35", - "type": "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18153_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18668_storage)" }, { - "astId": 11119, + "astId": 11964, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnetKeys", "offset": 0, @@ -494,59 +494,59 @@ ], "numberOfBytes": "1216" }, - "t_struct(IPCAddress)18443_storage": { + "t_struct(IPCAddress)18958_storage": { "encoding": "inplace", "label": "struct IPCAddress", "members": [ { - "astId": 18439, + "astId": 18954, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "subnetId", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18442, + "astId": 18957, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "rawAddress", "offset": 0, "slot": "2", - "type": "t_struct(FvmAddress)18218_storage" + "type": "t_struct(FvmAddress)18733_storage" } ], "numberOfBytes": "128" }, - "t_struct(IpcEnvelope)18187_storage": { + "t_struct(IpcEnvelope)18702_storage": { "encoding": "inplace", "label": "struct IpcEnvelope", "members": [ { - "astId": 18169, + "astId": 18684, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(IpcMsgKind)18164" + "type": "t_enum(IpcMsgKind)18679" }, { - "astId": 18173, + "astId": 18688, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "to", "offset": 0, "slot": "1", - "type": "t_struct(IPCAddress)18443_storage" + "type": "t_struct(IPCAddress)18958_storage" }, { - "astId": 18177, + "astId": 18692, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "from", "offset": 0, "slot": "5", - "type": "t_struct(IPCAddress)18443_storage" + "type": "t_struct(IPCAddress)18958_storage" }, { - "astId": 18180, + "astId": 18695, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "nonce", "offset": 0, @@ -554,7 +554,7 @@ "type": "t_uint64" }, { - "astId": 18183, + "astId": 18698, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "value", "offset": 0, @@ -562,7 +562,7 @@ "type": "t_uint256" }, { - "astId": 18186, + "astId": 18701, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "message", "offset": 0, @@ -572,35 +572,35 @@ ], "numberOfBytes": "384" }, - "t_struct(MaxPQ)16610_storage": { + "t_struct(MaxPQ)17125_storage": { "encoding": "inplace", "label": "struct MaxPQ", "members": [ { - "astId": 16609, + "astId": 17124, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)17858_storage" + "type": "t_struct(PQ)18373_storage" } ], "numberOfBytes": "96" }, - "t_struct(Membership)18459_storage": { + "t_struct(Membership)18974_storage": { "encoding": "inplace", "label": "struct Membership", "members": [ { - "astId": 18456, + "astId": 18971, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validators", "offset": 0, "slot": "0", - "type": "t_array(t_struct(Validator)18451_storage)dyn_storage" + "type": "t_array(t_struct(Validator)18966_storage)dyn_storage" }, { - "astId": 18458, + "astId": 18973, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "configurationNumber", "offset": 0, @@ -610,27 +610,27 @@ ], "numberOfBytes": "64" }, - "t_struct(MinPQ)17228_storage": { + "t_struct(MinPQ)17743_storage": { "encoding": "inplace", "label": "struct MinPQ", "members": [ { - "astId": 17227, + "astId": 17742, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)17858_storage" + "type": "t_struct(PQ)18373_storage" } ], "numberOfBytes": "96" }, - "t_struct(PQ)17858_storage": { + "t_struct(PQ)18373_storage": { "encoding": "inplace", "label": "struct PQ", "members": [ { - "astId": 17847, + "astId": 18362, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "size", "offset": 0, @@ -638,7 +638,7 @@ "type": "t_uint16" }, { - "astId": 17852, + "astId": 18367, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "addressToPos", "offset": 0, @@ -646,7 +646,7 @@ "type": "t_mapping(t_address,t_uint16)" }, { - "astId": 17857, + "astId": 18372, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "posToAddress", "offset": 0, @@ -656,12 +656,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ParentFinality)18119_storage": { + "t_struct(ParentFinality)18634_storage": { "encoding": "inplace", "label": "struct ParentFinality", "members": [ { - "astId": 18116, + "astId": 18631, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "height", "offset": 0, @@ -669,7 +669,7 @@ "type": "t_uint256" }, { - "astId": 18118, + "astId": 18633, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "blockHash", "offset": 0, @@ -679,35 +679,35 @@ ], "numberOfBytes": "64" }, - "t_struct(ParentValidatorsTracker)18435_storage": { + "t_struct(ParentValidatorsTracker)18950_storage": { "encoding": "inplace", "label": "struct ParentValidatorsTracker", "members": [ { - "astId": 18431, + "astId": 18946, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validators", "offset": 0, "slot": "0", - "type": "t_struct(ValidatorSet)18427_storage" + "type": "t_struct(ValidatorSet)18942_storage" }, { - "astId": 18434, + "astId": 18949, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "changes", "offset": 0, "slot": "9", - "type": "t_struct(StakingChangeLog)18350_storage" + "type": "t_struct(StakingChangeLog)18865_storage" } ], "numberOfBytes": "352" }, - "t_struct(QuorumInfo)18250_storage": { + "t_struct(QuorumInfo)18765_storage": { "encoding": "inplace", "label": "struct QuorumInfo", "members": [ { - "astId": 18237, + "astId": 18752, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "hash", "offset": 0, @@ -715,7 +715,7 @@ "type": "t_bytes32" }, { - "astId": 18240, + "astId": 18755, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "rootHash", "offset": 0, @@ -723,7 +723,7 @@ "type": "t_bytes32" }, { - "astId": 18243, + "astId": 18758, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "threshold", "offset": 0, @@ -731,7 +731,7 @@ "type": "t_uint256" }, { - "astId": 18246, + "astId": 18761, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "currentWeight", "offset": 0, @@ -739,7 +739,7 @@ "type": "t_uint256" }, { - "astId": 18249, + "astId": 18764, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "reached", "offset": 0, @@ -749,20 +749,20 @@ ], "numberOfBytes": "160" }, - "t_struct(QuorumMap)18282_storage": { + "t_struct(QuorumMap)18797_storage": { "encoding": "inplace", "label": "struct QuorumMap", "members": [ { - "astId": 18255, + "astId": 18770, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "quorumObjKind", "offset": 0, "slot": "0", - "type": "t_enum(QuorumObjKind)18233" + "type": "t_enum(QuorumObjKind)18748" }, { - "astId": 18258, + "astId": 18773, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "retentionHeight", "offset": 0, @@ -770,15 +770,15 @@ "type": "t_uint256" }, { - "astId": 18264, + "astId": 18779, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "quorumInfo", "offset": 0, "slot": "2", - "type": "t_mapping(t_uint256,t_struct(QuorumInfo)18250_storage)" + "type": "t_mapping(t_uint256,t_struct(QuorumInfo)18765_storage)" }, { - "astId": 18268, + "astId": 18783, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "incompleteQuorums", "offset": 0, @@ -786,7 +786,7 @@ "type": "t_struct(UintSet)3616_storage" }, { - "astId": 18274, + "astId": 18789, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "quorumSignatureSenders", "offset": 0, @@ -794,7 +794,7 @@ "type": "t_mapping(t_uint256,t_struct(AddressSet)3459_storage)" }, { - "astId": 18281, + "astId": 18796, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "quorumSignatures", "offset": 0, @@ -827,20 +827,20 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingChange)18329_storage": { + "t_struct(StakingChange)18844_storage": { "encoding": "inplace", "label": "struct StakingChange", "members": [ { - "astId": 18324, + "astId": 18839, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "op", "offset": 0, "slot": "0", - "type": "t_enum(StakingOperation)18320" + "type": "t_enum(StakingOperation)18835" }, { - "astId": 18326, + "astId": 18841, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "payload", "offset": 0, @@ -848,7 +848,7 @@ "type": "t_bytes_storage" }, { - "astId": 18328, + "astId": 18843, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validator", "offset": 0, @@ -858,12 +858,12 @@ ], "numberOfBytes": "96" }, - "t_struct(StakingChangeLog)18350_storage": { + "t_struct(StakingChangeLog)18865_storage": { "encoding": "inplace", "label": "struct StakingChangeLog", "members": [ { - "astId": 18340, + "astId": 18855, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "nextConfigurationNumber", "offset": 0, @@ -871,7 +871,7 @@ "type": "t_uint64" }, { - "astId": 18343, + "astId": 18858, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "startConfigurationNumber", "offset": 8, @@ -879,22 +879,22 @@ "type": "t_uint64" }, { - "astId": 18349, + "astId": 18864, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "changes", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint64,t_struct(StakingChange)18329_storage)" + "type": "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)" } ], "numberOfBytes": "64" }, - "t_struct(Subnet)18314_storage": { + "t_struct(Subnet)18829_storage": { "encoding": "inplace", "label": "struct Subnet", "members": [ { - "astId": 18302, + "astId": 18817, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "stake", "offset": 0, @@ -902,7 +902,7 @@ "type": "t_uint256" }, { - "astId": 18304, + "astId": 18819, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "genesisEpoch", "offset": 0, @@ -910,7 +910,7 @@ "type": "t_uint256" }, { - "astId": 18306, + "astId": 18821, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "circSupply", "offset": 0, @@ -918,7 +918,7 @@ "type": "t_uint256" }, { - "astId": 18308, + "astId": 18823, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "topDownNonce", "offset": 0, @@ -926,7 +926,7 @@ "type": "t_uint64" }, { - "astId": 18310, + "astId": 18825, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "appliedBottomUpNonce", "offset": 8, @@ -934,22 +934,22 @@ "type": "t_uint64" }, { - "astId": 18313, + "astId": 18828, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "id", "offset": 0, "slot": "4", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" } ], "numberOfBytes": "192" }, - "t_struct(SubnetID)18299_storage": { + "t_struct(SubnetID)18814_storage": { "encoding": "inplace", "label": "struct SubnetID", "members": [ { - "astId": 18294, + "astId": 18809, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "root", "offset": 0, @@ -957,7 +957,7 @@ "type": "t_uint64" }, { - "astId": 18298, + "astId": 18813, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "route", "offset": 0, @@ -982,12 +982,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Validator)18451_storage": { + "t_struct(Validator)18966_storage": { "encoding": "inplace", "label": "struct Validator", "members": [ { - "astId": 18446, + "astId": 18961, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "weight", "offset": 0, @@ -995,7 +995,7 @@ "type": "t_uint256" }, { - "astId": 18448, + "astId": 18963, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "addr", "offset": 0, @@ -1003,7 +1003,7 @@ "type": "t_address" }, { - "astId": 18450, + "astId": 18965, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "metadata", "offset": 0, @@ -1013,12 +1013,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ValidatorInfo)18392_storage": { + "t_struct(ValidatorInfo)18907_storage": { "encoding": "inplace", "label": "struct ValidatorInfo", "members": [ { - "astId": 18384, + "astId": 18899, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "federatedPower", "offset": 0, @@ -1026,7 +1026,7 @@ "type": "t_uint256" }, { - "astId": 18386, + "astId": 18901, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "confirmedCollateral", "offset": 0, @@ -1034,7 +1034,7 @@ "type": "t_uint256" }, { - "astId": 18388, + "astId": 18903, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "totalCollateral", "offset": 0, @@ -1042,7 +1042,7 @@ "type": "t_uint256" }, { - "astId": 18391, + "astId": 18906, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "metadata", "offset": 0, @@ -1052,20 +1052,20 @@ ], "numberOfBytes": "128" }, - "t_struct(ValidatorSet)18427_storage": { + "t_struct(ValidatorSet)18942_storage": { "encoding": "inplace", "label": "struct ValidatorSet", "members": [ { - "astId": 18406, + "astId": 18921, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "permissionMode", "offset": 0, "slot": "0", - "type": "t_enum(PermissionMode)18397" + "type": "t_enum(PermissionMode)18912" }, { - "astId": 18409, + "astId": 18924, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "activeLimit", "offset": 1, @@ -1073,7 +1073,7 @@ "type": "t_uint16" }, { - "astId": 18412, + "astId": 18927, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "totalConfirmedCollateral", "offset": 0, @@ -1081,28 +1081,28 @@ "type": "t_uint256" }, { - "astId": 18418, + "astId": 18933, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "validators", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(ValidatorInfo)18392_storage)" + "type": "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)" }, { - "astId": 18422, + "astId": 18937, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "activeValidators", "offset": 0, "slot": "3", - "type": "t_struct(MinPQ)17228_storage" + "type": "t_struct(MinPQ)17743_storage" }, { - "astId": 18426, + "astId": 18941, "contract": "contracts/lib/LibGatewayActorStorage.sol:GatewayActorModifiers", "label": "waitingValidators", "offset": 0, "slot": "6", - "type": "t_struct(MaxPQ)16610_storage" + "type": "t_struct(MaxPQ)17125_storage" } ], "numberOfBytes": "288" diff --git a/contracts/.storage-layouts/GatewayDiamond.json b/contracts/.storage-layouts/GatewayDiamond.json index 759623a30e..8d68e6165a 100644 --- a/contracts/.storage-layouts/GatewayDiamond.json +++ b/contracts/.storage-layouts/GatewayDiamond.json @@ -6,7 +6,7 @@ "label": "s", "offset": 0, "slot": "0", - "type": "t_struct(GatewayActorStorage)11120_storage" + "type": "t_struct(GatewayActorStorage)11965_storage" } ], "types": { @@ -27,14 +27,14 @@ "label": "bytes32[]", "numberOfBytes": "32" }, - "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage": { - "base": "t_struct(IpcEnvelope)18187_storage", + "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage": { + "base": "t_struct(IpcEnvelope)18702_storage", "encoding": "dynamic_array", "label": "struct IpcEnvelope[]", "numberOfBytes": "32" }, - "t_array(t_struct(Validator)18451_storage)dyn_storage": { - "base": "t_struct(Validator)18451_storage", + "t_array(t_struct(Validator)18966_storage)dyn_storage": { + "base": "t_struct(Validator)18966_storage", "encoding": "dynamic_array", "label": "struct Validator[]", "numberOfBytes": "32" @@ -54,22 +54,22 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_enum(IpcMsgKind)18164": { + "t_enum(IpcMsgKind)18679": { "encoding": "inplace", "label": "enum IpcMsgKind", "numberOfBytes": "1" }, - "t_enum(PermissionMode)18397": { + "t_enum(PermissionMode)18912": { "encoding": "inplace", "label": "enum PermissionMode", "numberOfBytes": "1" }, - "t_enum(QuorumObjKind)18233": { + "t_enum(QuorumObjKind)18748": { "encoding": "inplace", "label": "enum QuorumObjKind", "numberOfBytes": "1" }, - "t_enum(StakingOperation)18320": { + "t_enum(StakingOperation)18835": { "encoding": "inplace", "label": "enum StakingOperation", "numberOfBytes": "1" @@ -81,12 +81,12 @@ "numberOfBytes": "32", "value": "t_bytes_storage" }, - "t_mapping(t_address,t_struct(ValidatorInfo)18392_storage)": { + "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ValidatorInfo)", "numberOfBytes": "32", - "value": "t_struct(ValidatorInfo)18392_storage" + "value": "t_struct(ValidatorInfo)18907_storage" }, "t_mapping(t_address,t_uint16)": { "encoding": "mapping", @@ -95,19 +95,19 @@ "numberOfBytes": "32", "value": "t_uint16" }, - "t_mapping(t_bytes32,t_struct(IpcEnvelope)18187_storage)": { + "t_mapping(t_bytes32,t_struct(IpcEnvelope)18702_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct IpcEnvelope)", "numberOfBytes": "32", - "value": "t_struct(IpcEnvelope)18187_storage" + "value": "t_struct(IpcEnvelope)18702_storage" }, - "t_mapping(t_bytes32,t_struct(Subnet)18314_storage)": { + "t_mapping(t_bytes32,t_struct(Subnet)18829_storage)": { "encoding": "mapping", "key": "t_bytes32", "label": "mapping(bytes32 => struct Subnet)", "numberOfBytes": "32", - "value": "t_struct(Subnet)18314_storage" + "value": "t_struct(Subnet)18829_storage" }, "t_mapping(t_bytes32,t_uint256)": { "encoding": "mapping", @@ -137,40 +137,40 @@ "numberOfBytes": "32", "value": "t_struct(AddressSet)3459_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18139_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpCheckpoint)", "numberOfBytes": "32", - "value": "t_struct(BottomUpCheckpoint)18139_storage" + "value": "t_struct(BottomUpCheckpoint)18654_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18153_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18668_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpMsgBatch)", "numberOfBytes": "32", - "value": "t_struct(BottomUpMsgBatch)18153_storage" + "value": "t_struct(BottomUpMsgBatch)18668_storage" }, - "t_mapping(t_uint256,t_struct(ParentFinality)18119_storage)": { + "t_mapping(t_uint256,t_struct(ParentFinality)18634_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct ParentFinality)", "numberOfBytes": "32", - "value": "t_struct(ParentFinality)18119_storage" + "value": "t_struct(ParentFinality)18634_storage" }, - "t_mapping(t_uint256,t_struct(QuorumInfo)18250_storage)": { + "t_mapping(t_uint256,t_struct(QuorumInfo)18765_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct QuorumInfo)", "numberOfBytes": "32", - "value": "t_struct(QuorumInfo)18250_storage" + "value": "t_struct(QuorumInfo)18765_storage" }, - "t_mapping(t_uint64,t_struct(StakingChange)18329_storage)": { + "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)": { "encoding": "mapping", "key": "t_uint64", "label": "mapping(uint64 => struct StakingChange)", "numberOfBytes": "32", - "value": "t_struct(StakingChange)18329_storage" + "value": "t_struct(StakingChange)18844_storage" }, "t_struct(AddressSet)3459_storage": { "encoding": "inplace", @@ -187,20 +187,20 @@ ], "numberOfBytes": "64" }, - "t_struct(BottomUpCheckpoint)18139_storage": { + "t_struct(BottomUpCheckpoint)18654_storage": { "encoding": "inplace", "label": "struct BottomUpCheckpoint", "members": [ { - "astId": 18124, + "astId": 18639, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18127, + "astId": 18642, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "blockHeight", "offset": 0, @@ -208,7 +208,7 @@ "type": "t_uint256" }, { - "astId": 18130, + "astId": 18645, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "blockHash", "offset": 0, @@ -216,7 +216,7 @@ "type": "t_bytes32" }, { - "astId": 18133, + "astId": 18648, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "nextConfigurationNumber", "offset": 0, @@ -224,30 +224,30 @@ "type": "t_uint64" }, { - "astId": 18138, + "astId": 18653, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "msgs", "offset": 0, "slot": "5", - "type": "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" } ], "numberOfBytes": "192" }, - "t_struct(BottomUpMsgBatch)18153_storage": { + "t_struct(BottomUpMsgBatch)18668_storage": { "encoding": "inplace", "label": "struct BottomUpMsgBatch", "members": [ { - "astId": 18144, + "astId": 18659, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18147, + "astId": 18662, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "blockHeight", "offset": 0, @@ -255,12 +255,12 @@ "type": "t_uint256" }, { - "astId": 18152, + "astId": 18667, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "msgs", "offset": 0, "slot": "3", - "type": "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" } ], "numberOfBytes": "128" @@ -280,12 +280,12 @@ ], "numberOfBytes": "64" }, - "t_struct(FvmAddress)18218_storage": { + "t_struct(FvmAddress)18733_storage": { "encoding": "inplace", "label": "struct FvmAddress", "members": [ { - "astId": 18215, + "astId": 18730, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "addrType", "offset": 0, @@ -293,7 +293,7 @@ "type": "t_uint8" }, { - "astId": 18217, + "astId": 18732, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "payload", "offset": 0, @@ -303,12 +303,12 @@ ], "numberOfBytes": "64" }, - "t_struct(GatewayActorStorage)11120_storage": { + "t_struct(GatewayActorStorage)11965_storage": { "encoding": "inplace", "label": "struct GatewayActorStorage", "members": [ { - "astId": 11032, + "astId": 11877, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "latestParentHeight", "offset": 0, @@ -316,7 +316,7 @@ "type": "t_uint256" }, { - "astId": 11035, + "astId": 11880, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpCheckPeriod", "offset": 0, @@ -324,7 +324,7 @@ "type": "t_uint256" }, { - "astId": 11038, + "astId": 11883, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpMsgBatchPeriod", "offset": 0, @@ -332,7 +332,7 @@ "type": "t_uint256" }, { - "astId": 11041, + "astId": 11886, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpNonce", "offset": 0, @@ -340,7 +340,7 @@ "type": "t_uint64" }, { - "astId": 11044, + "astId": 11889, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "appliedTopDownNonce", "offset": 8, @@ -348,7 +348,7 @@ "type": "t_uint64" }, { - "astId": 11047, + "astId": 11892, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "totalSubnets", "offset": 16, @@ -356,7 +356,7 @@ "type": "t_uint64" }, { - "astId": 11050, + "astId": 11895, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "maxMsgsPerBottomUpBatch", "offset": 24, @@ -364,7 +364,7 @@ "type": "t_uint64" }, { - "astId": 11053, + "astId": 11898, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "majorityPercentage", "offset": 0, @@ -372,7 +372,7 @@ "type": "t_uint8" }, { - "astId": 11056, + "astId": 11901, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "commitSha", "offset": 0, @@ -380,7 +380,7 @@ "type": "t_bytes32" }, { - "astId": 11059, + "astId": 11904, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "maxTreeDepth", "offset": 0, @@ -388,7 +388,7 @@ "type": "t_uint8" }, { - "astId": 11062, + "astId": 11907, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "generalPurposeCrossMsg", "offset": 1, @@ -396,7 +396,7 @@ "type": "t_bool" }, { - "astId": 11065, + "astId": 11910, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "multiLevelCrossMsg", "offset": 2, @@ -404,87 +404,87 @@ "type": "t_bool" }, { - "astId": 11069, + "astId": 11914, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "currentMembership", "offset": 0, "slot": "7", - "type": "t_struct(Membership)18459_storage" + "type": "t_struct(Membership)18974_storage" }, { - "astId": 11073, + "astId": 11918, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "lastMembership", "offset": 0, "slot": "9", - "type": "t_struct(Membership)18459_storage" + "type": "t_struct(Membership)18974_storage" }, { - "astId": 11077, + "astId": 11922, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "checkpointQuorumMap", "offset": 0, "slot": "11", - "type": "t_struct(QuorumMap)18282_storage" + "type": "t_struct(QuorumMap)18797_storage" }, { - "astId": 11081, + "astId": 11926, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "networkName", "offset": 0, "slot": "18", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 11085, + "astId": 11930, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validatorsTracker", "offset": 0, "slot": "20", - "type": "t_struct(ParentValidatorsTracker)18435_storage" + "type": "t_struct(ParentValidatorsTracker)18950_storage" }, { - "astId": 11091, + "astId": 11936, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnets", "offset": 0, "slot": "31", - "type": "t_mapping(t_bytes32,t_struct(Subnet)18314_storage)" + "type": "t_mapping(t_bytes32,t_struct(Subnet)18829_storage)" }, { - "astId": 11097, + "astId": 11942, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "finalitiesMap", "offset": 0, "slot": "32", - "type": "t_mapping(t_uint256,t_struct(ParentFinality)18119_storage)" + "type": "t_mapping(t_uint256,t_struct(ParentFinality)18634_storage)" }, { - "astId": 11103, + "astId": 11948, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "postbox", "offset": 0, "slot": "33", - "type": "t_mapping(t_bytes32,t_struct(IpcEnvelope)18187_storage)" + "type": "t_mapping(t_bytes32,t_struct(IpcEnvelope)18702_storage)" }, { - "astId": 11109, + "astId": 11954, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpCheckpoints", "offset": 0, "slot": "34", - "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18139_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)" }, { - "astId": 11115, + "astId": 11960, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "bottomUpMsgBatches", "offset": 0, "slot": "35", - "type": "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18153_storage)" + "type": "t_mapping(t_uint256,t_struct(BottomUpMsgBatch)18668_storage)" }, { - "astId": 11119, + "astId": 11964, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnetKeys", "offset": 0, @@ -494,59 +494,59 @@ ], "numberOfBytes": "1216" }, - "t_struct(IPCAddress)18443_storage": { + "t_struct(IPCAddress)18958_storage": { "encoding": "inplace", "label": "struct IPCAddress", "members": [ { - "astId": 18439, + "astId": 18954, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "subnetId", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18442, + "astId": 18957, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "rawAddress", "offset": 0, "slot": "2", - "type": "t_struct(FvmAddress)18218_storage" + "type": "t_struct(FvmAddress)18733_storage" } ], "numberOfBytes": "128" }, - "t_struct(IpcEnvelope)18187_storage": { + "t_struct(IpcEnvelope)18702_storage": { "encoding": "inplace", "label": "struct IpcEnvelope", "members": [ { - "astId": 18169, + "astId": 18684, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(IpcMsgKind)18164" + "type": "t_enum(IpcMsgKind)18679" }, { - "astId": 18173, + "astId": 18688, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "to", "offset": 0, "slot": "1", - "type": "t_struct(IPCAddress)18443_storage" + "type": "t_struct(IPCAddress)18958_storage" }, { - "astId": 18177, + "astId": 18692, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "from", "offset": 0, "slot": "5", - "type": "t_struct(IPCAddress)18443_storage" + "type": "t_struct(IPCAddress)18958_storage" }, { - "astId": 18180, + "astId": 18695, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "nonce", "offset": 0, @@ -554,7 +554,7 @@ "type": "t_uint64" }, { - "astId": 18183, + "astId": 18698, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "value", "offset": 0, @@ -562,7 +562,7 @@ "type": "t_uint256" }, { - "astId": 18186, + "astId": 18701, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "message", "offset": 0, @@ -572,35 +572,35 @@ ], "numberOfBytes": "384" }, - "t_struct(MaxPQ)16610_storage": { + "t_struct(MaxPQ)17125_storage": { "encoding": "inplace", "label": "struct MaxPQ", "members": [ { - "astId": 16609, + "astId": 17124, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)17858_storage" + "type": "t_struct(PQ)18373_storage" } ], "numberOfBytes": "96" }, - "t_struct(Membership)18459_storage": { + "t_struct(Membership)18974_storage": { "encoding": "inplace", "label": "struct Membership", "members": [ { - "astId": 18456, + "astId": 18971, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validators", "offset": 0, "slot": "0", - "type": "t_array(t_struct(Validator)18451_storage)dyn_storage" + "type": "t_array(t_struct(Validator)18966_storage)dyn_storage" }, { - "astId": 18458, + "astId": 18973, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "configurationNumber", "offset": 0, @@ -610,27 +610,27 @@ ], "numberOfBytes": "64" }, - "t_struct(MinPQ)17228_storage": { + "t_struct(MinPQ)17743_storage": { "encoding": "inplace", "label": "struct MinPQ", "members": [ { - "astId": 17227, + "astId": 17742, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)17858_storage" + "type": "t_struct(PQ)18373_storage" } ], "numberOfBytes": "96" }, - "t_struct(PQ)17858_storage": { + "t_struct(PQ)18373_storage": { "encoding": "inplace", "label": "struct PQ", "members": [ { - "astId": 17847, + "astId": 18362, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "size", "offset": 0, @@ -638,7 +638,7 @@ "type": "t_uint16" }, { - "astId": 17852, + "astId": 18367, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "addressToPos", "offset": 0, @@ -646,7 +646,7 @@ "type": "t_mapping(t_address,t_uint16)" }, { - "astId": 17857, + "astId": 18372, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "posToAddress", "offset": 0, @@ -656,12 +656,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ParentFinality)18119_storage": { + "t_struct(ParentFinality)18634_storage": { "encoding": "inplace", "label": "struct ParentFinality", "members": [ { - "astId": 18116, + "astId": 18631, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "height", "offset": 0, @@ -669,7 +669,7 @@ "type": "t_uint256" }, { - "astId": 18118, + "astId": 18633, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "blockHash", "offset": 0, @@ -679,35 +679,35 @@ ], "numberOfBytes": "64" }, - "t_struct(ParentValidatorsTracker)18435_storage": { + "t_struct(ParentValidatorsTracker)18950_storage": { "encoding": "inplace", "label": "struct ParentValidatorsTracker", "members": [ { - "astId": 18431, + "astId": 18946, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validators", "offset": 0, "slot": "0", - "type": "t_struct(ValidatorSet)18427_storage" + "type": "t_struct(ValidatorSet)18942_storage" }, { - "astId": 18434, + "astId": 18949, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "changes", "offset": 0, "slot": "9", - "type": "t_struct(StakingChangeLog)18350_storage" + "type": "t_struct(StakingChangeLog)18865_storage" } ], "numberOfBytes": "352" }, - "t_struct(QuorumInfo)18250_storage": { + "t_struct(QuorumInfo)18765_storage": { "encoding": "inplace", "label": "struct QuorumInfo", "members": [ { - "astId": 18237, + "astId": 18752, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "hash", "offset": 0, @@ -715,7 +715,7 @@ "type": "t_bytes32" }, { - "astId": 18240, + "astId": 18755, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "rootHash", "offset": 0, @@ -723,7 +723,7 @@ "type": "t_bytes32" }, { - "astId": 18243, + "astId": 18758, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "threshold", "offset": 0, @@ -731,7 +731,7 @@ "type": "t_uint256" }, { - "astId": 18246, + "astId": 18761, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "currentWeight", "offset": 0, @@ -739,7 +739,7 @@ "type": "t_uint256" }, { - "astId": 18249, + "astId": 18764, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "reached", "offset": 0, @@ -749,20 +749,20 @@ ], "numberOfBytes": "160" }, - "t_struct(QuorumMap)18282_storage": { + "t_struct(QuorumMap)18797_storage": { "encoding": "inplace", "label": "struct QuorumMap", "members": [ { - "astId": 18255, + "astId": 18770, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "quorumObjKind", "offset": 0, "slot": "0", - "type": "t_enum(QuorumObjKind)18233" + "type": "t_enum(QuorumObjKind)18748" }, { - "astId": 18258, + "astId": 18773, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "retentionHeight", "offset": 0, @@ -770,15 +770,15 @@ "type": "t_uint256" }, { - "astId": 18264, + "astId": 18779, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "quorumInfo", "offset": 0, "slot": "2", - "type": "t_mapping(t_uint256,t_struct(QuorumInfo)18250_storage)" + "type": "t_mapping(t_uint256,t_struct(QuorumInfo)18765_storage)" }, { - "astId": 18268, + "astId": 18783, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "incompleteQuorums", "offset": 0, @@ -786,7 +786,7 @@ "type": "t_struct(UintSet)3616_storage" }, { - "astId": 18274, + "astId": 18789, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "quorumSignatureSenders", "offset": 0, @@ -794,7 +794,7 @@ "type": "t_mapping(t_uint256,t_struct(AddressSet)3459_storage)" }, { - "astId": 18281, + "astId": 18796, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "quorumSignatures", "offset": 0, @@ -827,20 +827,20 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingChange)18329_storage": { + "t_struct(StakingChange)18844_storage": { "encoding": "inplace", "label": "struct StakingChange", "members": [ { - "astId": 18324, + "astId": 18839, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "op", "offset": 0, "slot": "0", - "type": "t_enum(StakingOperation)18320" + "type": "t_enum(StakingOperation)18835" }, { - "astId": 18326, + "astId": 18841, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "payload", "offset": 0, @@ -848,7 +848,7 @@ "type": "t_bytes_storage" }, { - "astId": 18328, + "astId": 18843, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validator", "offset": 0, @@ -858,12 +858,12 @@ ], "numberOfBytes": "96" }, - "t_struct(StakingChangeLog)18350_storage": { + "t_struct(StakingChangeLog)18865_storage": { "encoding": "inplace", "label": "struct StakingChangeLog", "members": [ { - "astId": 18340, + "astId": 18855, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "nextConfigurationNumber", "offset": 0, @@ -871,7 +871,7 @@ "type": "t_uint64" }, { - "astId": 18343, + "astId": 18858, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "startConfigurationNumber", "offset": 8, @@ -879,22 +879,22 @@ "type": "t_uint64" }, { - "astId": 18349, + "astId": 18864, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "changes", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint64,t_struct(StakingChange)18329_storage)" + "type": "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)" } ], "numberOfBytes": "64" }, - "t_struct(Subnet)18314_storage": { + "t_struct(Subnet)18829_storage": { "encoding": "inplace", "label": "struct Subnet", "members": [ { - "astId": 18302, + "astId": 18817, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "stake", "offset": 0, @@ -902,7 +902,7 @@ "type": "t_uint256" }, { - "astId": 18304, + "astId": 18819, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "genesisEpoch", "offset": 0, @@ -910,7 +910,7 @@ "type": "t_uint256" }, { - "astId": 18306, + "astId": 18821, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "circSupply", "offset": 0, @@ -918,7 +918,7 @@ "type": "t_uint256" }, { - "astId": 18308, + "astId": 18823, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "topDownNonce", "offset": 0, @@ -926,7 +926,7 @@ "type": "t_uint64" }, { - "astId": 18310, + "astId": 18825, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "appliedBottomUpNonce", "offset": 8, @@ -934,22 +934,22 @@ "type": "t_uint64" }, { - "astId": 18313, + "astId": 18828, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "id", "offset": 0, "slot": "4", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" } ], "numberOfBytes": "192" }, - "t_struct(SubnetID)18299_storage": { + "t_struct(SubnetID)18814_storage": { "encoding": "inplace", "label": "struct SubnetID", "members": [ { - "astId": 18294, + "astId": 18809, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "root", "offset": 0, @@ -957,7 +957,7 @@ "type": "t_uint64" }, { - "astId": 18298, + "astId": 18813, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "route", "offset": 0, @@ -982,12 +982,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Validator)18451_storage": { + "t_struct(Validator)18966_storage": { "encoding": "inplace", "label": "struct Validator", "members": [ { - "astId": 18446, + "astId": 18961, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "weight", "offset": 0, @@ -995,7 +995,7 @@ "type": "t_uint256" }, { - "astId": 18448, + "astId": 18963, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "addr", "offset": 0, @@ -1003,7 +1003,7 @@ "type": "t_address" }, { - "astId": 18450, + "astId": 18965, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "metadata", "offset": 0, @@ -1013,12 +1013,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ValidatorInfo)18392_storage": { + "t_struct(ValidatorInfo)18907_storage": { "encoding": "inplace", "label": "struct ValidatorInfo", "members": [ { - "astId": 18384, + "astId": 18899, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "federatedPower", "offset": 0, @@ -1026,7 +1026,7 @@ "type": "t_uint256" }, { - "astId": 18386, + "astId": 18901, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "confirmedCollateral", "offset": 0, @@ -1034,7 +1034,7 @@ "type": "t_uint256" }, { - "astId": 18388, + "astId": 18903, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "totalCollateral", "offset": 0, @@ -1042,7 +1042,7 @@ "type": "t_uint256" }, { - "astId": 18391, + "astId": 18906, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "metadata", "offset": 0, @@ -1052,20 +1052,20 @@ ], "numberOfBytes": "128" }, - "t_struct(ValidatorSet)18427_storage": { + "t_struct(ValidatorSet)18942_storage": { "encoding": "inplace", "label": "struct ValidatorSet", "members": [ { - "astId": 18406, + "astId": 18921, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "permissionMode", "offset": 0, "slot": "0", - "type": "t_enum(PermissionMode)18397" + "type": "t_enum(PermissionMode)18912" }, { - "astId": 18409, + "astId": 18924, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "activeLimit", "offset": 1, @@ -1073,7 +1073,7 @@ "type": "t_uint16" }, { - "astId": 18412, + "astId": 18927, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "totalConfirmedCollateral", "offset": 0, @@ -1081,28 +1081,28 @@ "type": "t_uint256" }, { - "astId": 18418, + "astId": 18933, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "validators", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(ValidatorInfo)18392_storage)" + "type": "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)" }, { - "astId": 18422, + "astId": 18937, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "activeValidators", "offset": 0, "slot": "3", - "type": "t_struct(MinPQ)17228_storage" + "type": "t_struct(MinPQ)17743_storage" }, { - "astId": 18426, + "astId": 18941, "contract": "contracts/GatewayDiamond.sol:GatewayDiamond", "label": "waitingValidators", "offset": 0, "slot": "6", - "type": "t_struct(MaxPQ)16610_storage" + "type": "t_struct(MaxPQ)17125_storage" } ], "numberOfBytes": "288" diff --git a/contracts/.storage-layouts/SubnetActorDiamond.json b/contracts/.storage-layouts/SubnetActorDiamond.json index 5ebb51bd34..1a7511cd67 100644 --- a/contracts/.storage-layouts/SubnetActorDiamond.json +++ b/contracts/.storage-layouts/SubnetActorDiamond.json @@ -6,7 +6,7 @@ "label": "s", "offset": 0, "slot": "0", - "type": "t_struct(SubnetActorStorage)15339_storage" + "type": "t_struct(SubnetActorStorage)16379_storage" } ], "types": { @@ -27,14 +27,14 @@ "label": "bytes32[]", "numberOfBytes": "32" }, - "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage": { - "base": "t_struct(IpcEnvelope)18187_storage", + "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage": { + "base": "t_struct(IpcEnvelope)18702_storage", "encoding": "dynamic_array", "label": "struct IpcEnvelope[]", "numberOfBytes": "32" }, - "t_array(t_struct(Validator)18451_storage)dyn_storage": { - "base": "t_struct(Validator)18451_storage", + "t_array(t_struct(Validator)18966_storage)dyn_storage": { + "base": "t_struct(Validator)18966_storage", "encoding": "dynamic_array", "label": "struct Validator[]", "numberOfBytes": "32" @@ -54,31 +54,31 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_enum(ConsensusType)5472": { + "t_enum(AssetKind)18987": { + "encoding": "inplace", + "label": "enum AssetKind", + "numberOfBytes": "1" + }, + "t_enum(ConsensusType)5500": { "encoding": "inplace", "label": "enum ConsensusType", "numberOfBytes": "1" }, - "t_enum(IpcMsgKind)18164": { + "t_enum(IpcMsgKind)18679": { "encoding": "inplace", "label": "enum IpcMsgKind", "numberOfBytes": "1" }, - "t_enum(PermissionMode)18397": { + "t_enum(PermissionMode)18912": { "encoding": "inplace", "label": "enum PermissionMode", "numberOfBytes": "1" }, - "t_enum(StakingOperation)18320": { + "t_enum(StakingOperation)18835": { "encoding": "inplace", "label": "enum StakingOperation", "numberOfBytes": "1" }, - "t_enum(SupplyKind)18472": { - "encoding": "inplace", - "label": "enum SupplyKind", - "numberOfBytes": "1" - }, "t_int8": { "encoding": "inplace", "label": "int8", @@ -91,19 +91,19 @@ "numberOfBytes": "32", "value": "t_string_storage" }, - "t_mapping(t_address,t_struct(AddressStakingReleases)18369_storage)": { + "t_mapping(t_address,t_struct(AddressStakingReleases)18884_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct AddressStakingReleases)", "numberOfBytes": "32", - "value": "t_struct(AddressStakingReleases)18369_storage" + "value": "t_struct(AddressStakingReleases)18884_storage" }, - "t_mapping(t_address,t_struct(ValidatorInfo)18392_storage)": { + "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ValidatorInfo)", "numberOfBytes": "32", - "value": "t_struct(ValidatorInfo)18392_storage" + "value": "t_struct(ValidatorInfo)18907_storage" }, "t_mapping(t_address,t_uint16)": { "encoding": "mapping", @@ -133,26 +133,26 @@ "numberOfBytes": "32", "value": "t_address" }, - "t_mapping(t_uint16,t_struct(StakingRelease)18358_storage)": { + "t_mapping(t_uint16,t_struct(StakingRelease)18873_storage)": { "encoding": "mapping", "key": "t_uint16", "label": "mapping(uint16 => struct StakingRelease)", "numberOfBytes": "32", - "value": "t_struct(StakingRelease)18358_storage" + "value": "t_struct(StakingRelease)18873_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18139_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpCheckpoint)", "numberOfBytes": "32", - "value": "t_struct(BottomUpCheckpoint)18139_storage" + "value": "t_struct(BottomUpCheckpoint)18654_storage" }, - "t_mapping(t_uint64,t_struct(StakingChange)18329_storage)": { + "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)": { "encoding": "mapping", "key": "t_uint64", "label": "mapping(uint64 => struct StakingChange)", "numberOfBytes": "32", - "value": "t_struct(StakingChange)18329_storage" + "value": "t_struct(StakingChange)18844_storage" }, "t_string_storage": { "encoding": "bytes", @@ -174,12 +174,12 @@ ], "numberOfBytes": "64" }, - "t_struct(AddressStakingReleases)18369_storage": { + "t_struct(AddressStakingReleases)18884_storage": { "encoding": "inplace", "label": "struct AddressStakingReleases", "members": [ { - "astId": 18361, + "astId": 18876, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "length", "offset": 0, @@ -187,7 +187,7 @@ "type": "t_uint16" }, { - "astId": 18363, + "astId": 18878, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "startIdx", "offset": 2, @@ -195,30 +195,53 @@ "type": "t_uint16" }, { - "astId": 18368, + "astId": 18883, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "releases", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint16,t_struct(StakingRelease)18358_storage)" + "type": "t_mapping(t_uint16,t_struct(StakingRelease)18873_storage)" } ], "numberOfBytes": "64" }, - "t_struct(BottomUpCheckpoint)18139_storage": { + "t_struct(Asset)18983_storage": { + "encoding": "inplace", + "label": "struct Asset", + "members": [ + { + "astId": 18979, + "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", + "label": "kind", + "offset": 0, + "slot": "0", + "type": "t_enum(AssetKind)18987" + }, + { + "astId": 18982, + "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", + "label": "tokenAddress", + "offset": 1, + "slot": "0", + "type": "t_address" + } + ], + "numberOfBytes": "32" + }, + "t_struct(BottomUpCheckpoint)18654_storage": { "encoding": "inplace", "label": "struct BottomUpCheckpoint", "members": [ { - "astId": 18124, + "astId": 18639, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18127, + "astId": 18642, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "blockHeight", "offset": 0, @@ -226,7 +249,7 @@ "type": "t_uint256" }, { - "astId": 18130, + "astId": 18645, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "blockHash", "offset": 0, @@ -234,7 +257,7 @@ "type": "t_bytes32" }, { - "astId": 18133, + "astId": 18648, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "nextConfigurationNumber", "offset": 0, @@ -242,22 +265,22 @@ "type": "t_uint64" }, { - "astId": 18138, + "astId": 18653, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "msgs", "offset": 0, "slot": "5", - "type": "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" } ], "numberOfBytes": "192" }, - "t_struct(FvmAddress)18218_storage": { + "t_struct(FvmAddress)18733_storage": { "encoding": "inplace", "label": "struct FvmAddress", "members": [ { - "astId": 18215, + "astId": 18730, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "addrType", "offset": 0, @@ -265,7 +288,7 @@ "type": "t_uint8" }, { - "astId": 18217, + "astId": 18732, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "payload", "offset": 0, @@ -275,59 +298,59 @@ ], "numberOfBytes": "64" }, - "t_struct(IPCAddress)18443_storage": { + "t_struct(IPCAddress)18958_storage": { "encoding": "inplace", "label": "struct IPCAddress", "members": [ { - "astId": 18439, + "astId": 18954, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "subnetId", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18442, + "astId": 18957, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "rawAddress", "offset": 0, "slot": "2", - "type": "t_struct(FvmAddress)18218_storage" + "type": "t_struct(FvmAddress)18733_storage" } ], "numberOfBytes": "128" }, - "t_struct(IpcEnvelope)18187_storage": { + "t_struct(IpcEnvelope)18702_storage": { "encoding": "inplace", "label": "struct IpcEnvelope", "members": [ { - "astId": 18169, + "astId": 18684, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(IpcMsgKind)18164" + "type": "t_enum(IpcMsgKind)18679" }, { - "astId": 18173, + "astId": 18688, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "to", "offset": 0, "slot": "1", - "type": "t_struct(IPCAddress)18443_storage" + "type": "t_struct(IPCAddress)18958_storage" }, { - "astId": 18177, + "astId": 18692, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "from", "offset": 0, "slot": "5", - "type": "t_struct(IPCAddress)18443_storage" + "type": "t_struct(IPCAddress)18958_storage" }, { - "astId": 18180, + "astId": 18695, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "nonce", "offset": 0, @@ -335,7 +358,7 @@ "type": "t_uint64" }, { - "astId": 18183, + "astId": 18698, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "value", "offset": 0, @@ -343,7 +366,7 @@ "type": "t_uint256" }, { - "astId": 18186, + "astId": 18701, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "message", "offset": 0, @@ -353,42 +376,42 @@ ], "numberOfBytes": "384" }, - "t_struct(MaxPQ)16610_storage": { + "t_struct(MaxPQ)17125_storage": { "encoding": "inplace", "label": "struct MaxPQ", "members": [ { - "astId": 16609, + "astId": 17124, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)17858_storage" + "type": "t_struct(PQ)18373_storage" } ], "numberOfBytes": "96" }, - "t_struct(MinPQ)17228_storage": { + "t_struct(MinPQ)17743_storage": { "encoding": "inplace", "label": "struct MinPQ", "members": [ { - "astId": 17227, + "astId": 17742, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)17858_storage" + "type": "t_struct(PQ)18373_storage" } ], "numberOfBytes": "96" }, - "t_struct(PQ)17858_storage": { + "t_struct(PQ)18373_storage": { "encoding": "inplace", "label": "struct PQ", "members": [ { - "astId": 17847, + "astId": 18362, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "size", "offset": 0, @@ -396,7 +419,7 @@ "type": "t_uint16" }, { - "astId": 17852, + "astId": 18367, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "addressToPos", "offset": 0, @@ -404,7 +427,7 @@ "type": "t_mapping(t_address,t_uint16)" }, { - "astId": 17857, + "astId": 18372, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "posToAddress", "offset": 0, @@ -437,20 +460,20 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingChange)18329_storage": { + "t_struct(StakingChange)18844_storage": { "encoding": "inplace", "label": "struct StakingChange", "members": [ { - "astId": 18324, + "astId": 18839, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "op", "offset": 0, "slot": "0", - "type": "t_enum(StakingOperation)18320" + "type": "t_enum(StakingOperation)18835" }, { - "astId": 18326, + "astId": 18841, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "payload", "offset": 0, @@ -458,7 +481,7 @@ "type": "t_bytes_storage" }, { - "astId": 18328, + "astId": 18843, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "validator", "offset": 0, @@ -468,12 +491,12 @@ ], "numberOfBytes": "96" }, - "t_struct(StakingChangeLog)18350_storage": { + "t_struct(StakingChangeLog)18865_storage": { "encoding": "inplace", "label": "struct StakingChangeLog", "members": [ { - "astId": 18340, + "astId": 18855, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "nextConfigurationNumber", "offset": 0, @@ -481,7 +504,7 @@ "type": "t_uint64" }, { - "astId": 18343, + "astId": 18858, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "startConfigurationNumber", "offset": 8, @@ -489,22 +512,22 @@ "type": "t_uint64" }, { - "astId": 18349, + "astId": 18864, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "changes", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint64,t_struct(StakingChange)18329_storage)" + "type": "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)" } ], "numberOfBytes": "64" }, - "t_struct(StakingRelease)18358_storage": { + "t_struct(StakingRelease)18873_storage": { "encoding": "inplace", "label": "struct StakingRelease", "members": [ { - "astId": 18354, + "astId": 18869, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "releaseAt", "offset": 0, @@ -512,7 +535,7 @@ "type": "t_uint256" }, { - "astId": 18357, + "astId": 18872, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "amount", "offset": 0, @@ -522,12 +545,12 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingReleaseQueue)18380_storage": { + "t_struct(StakingReleaseQueue)18895_storage": { "encoding": "inplace", "label": "struct StakingReleaseQueue", "members": [ { - "astId": 18373, + "astId": 18888, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "lockingDuration", "offset": 0, @@ -535,22 +558,22 @@ "type": "t_uint256" }, { - "astId": 18379, + "astId": 18894, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "releases", "offset": 0, "slot": "1", - "type": "t_mapping(t_address,t_struct(AddressStakingReleases)18369_storage)" + "type": "t_mapping(t_address,t_struct(AddressStakingReleases)18884_storage)" } ], "numberOfBytes": "64" }, - "t_struct(SubnetActorStorage)15339_storage": { + "t_struct(SubnetActorStorage)16379_storage": { "encoding": "inplace", "label": "struct SubnetActorStorage", "members": [ { - "astId": 15250, + "astId": 16286, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "genesisCircSupply", "offset": 0, @@ -558,7 +581,7 @@ "type": "t_uint256" }, { - "astId": 15253, + "astId": 16289, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "lastBottomUpCheckpointHeight", "offset": 0, @@ -566,7 +589,7 @@ "type": "t_uint256" }, { - "astId": 15256, + "astId": 16292, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "minActivationCollateral", "offset": 0, @@ -574,7 +597,7 @@ "type": "t_uint256" }, { - "astId": 15259, + "astId": 16295, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "bottomUpCheckPeriod", "offset": 0, @@ -582,7 +605,7 @@ "type": "t_uint256" }, { - "astId": 15261, + "astId": 16297, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "currentSubnetHash", "offset": 0, @@ -590,7 +613,7 @@ "type": "t_bytes32" }, { - "astId": 15264, + "astId": 16300, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "ipcGatewayAddr", "offset": 0, @@ -598,7 +621,7 @@ "type": "t_address" }, { - "astId": 15267, + "astId": 16303, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "maxMsgsPerBottomUpBatch", "offset": 20, @@ -606,7 +629,7 @@ "type": "t_uint64" }, { - "astId": 15270, + "astId": 16306, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "majorityPercentage", "offset": 28, @@ -614,7 +637,7 @@ "type": "t_uint8" }, { - "astId": 15273, + "astId": 16309, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "powerScale", "offset": 29, @@ -622,15 +645,15 @@ "type": "t_int8" }, { - "astId": 15277, + "astId": 16313, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "consensus", "offset": 30, "slot": "5", - "type": "t_enum(ConsensusType)5472" + "type": "t_enum(ConsensusType)5500" }, { - "astId": 15280, + "astId": 16316, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "bootstrapped", "offset": 31, @@ -638,7 +661,7 @@ "type": "t_bool" }, { - "astId": 15283, + "astId": 16319, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "minValidators", "offset": 0, @@ -646,7 +669,7 @@ "type": "t_uint64" }, { - "astId": 15286, + "astId": 16322, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "killed", "offset": 8, @@ -654,110 +677,118 @@ "type": "t_bool" }, { - "astId": 15290, + "astId": 16326, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "supplySource", "offset": 0, "slot": "7", - "type": "t_struct(SupplySource)18468_storage" + "type": "t_struct(Asset)18983_storage" }, { - "astId": 15294, + "astId": 16330, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", - "label": "parentId", + "label": "collateralSource", "offset": 0, "slot": "8", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(Asset)18983_storage" + }, + { + "astId": 16334, + "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", + "label": "parentId", + "offset": 0, + "slot": "9", + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 15298, + "astId": 16338, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "validatorSet", "offset": 0, - "slot": "10", - "type": "t_struct(ValidatorSet)18427_storage" + "slot": "11", + "type": "t_struct(ValidatorSet)18942_storage" }, { - "astId": 15302, + "astId": 16342, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "changeSet", "offset": 0, - "slot": "19", - "type": "t_struct(StakingChangeLog)18350_storage" + "slot": "20", + "type": "t_struct(StakingChangeLog)18865_storage" }, { - "astId": 15306, + "astId": 16346, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "releaseQueue", "offset": 0, - "slot": "21", - "type": "t_struct(StakingReleaseQueue)18380_storage" + "slot": "22", + "type": "t_struct(StakingReleaseQueue)18895_storage" }, { - "astId": 15311, + "astId": 16351, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "bootstrapNodes", "offset": 0, - "slot": "23", + "slot": "24", "type": "t_mapping(t_address,t_string_storage)" }, { - "astId": 15315, + "astId": 16355, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "bootstrapOwners", "offset": 0, - "slot": "24", + "slot": "25", "type": "t_struct(AddressSet)3459_storage" }, { - "astId": 15321, + "astId": 16361, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "committedCheckpoints", "offset": 0, - "slot": "26", - "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18139_storage)" + "slot": "27", + "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)" }, { - "astId": 15326, + "astId": 16366, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "genesisValidators", "offset": 0, - "slot": "27", - "type": "t_array(t_struct(Validator)18451_storage)dyn_storage" + "slot": "28", + "type": "t_array(t_struct(Validator)18966_storage)dyn_storage" }, { - "astId": 15331, + "astId": 16371, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "genesisBalance", "offset": 0, - "slot": "28", + "slot": "29", "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 15335, + "astId": 16375, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "genesisBalanceKeys", "offset": 0, - "slot": "29", + "slot": "30", "type": "t_array(t_address)dyn_storage" }, { - "astId": 15338, + "astId": 16378, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "validatorGater", "offset": 0, - "slot": "30", + "slot": "31", "type": "t_address" } ], - "numberOfBytes": "992" + "numberOfBytes": "1024" }, - "t_struct(SubnetID)18299_storage": { + "t_struct(SubnetID)18814_storage": { "encoding": "inplace", "label": "struct SubnetID", "members": [ { - "astId": 18294, + "astId": 18809, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "root", "offset": 0, @@ -765,7 +796,7 @@ "type": "t_uint64" }, { - "astId": 18298, + "astId": 18813, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "route", "offset": 0, @@ -775,35 +806,12 @@ ], "numberOfBytes": "64" }, - "t_struct(SupplySource)18468_storage": { - "encoding": "inplace", - "label": "struct SupplySource", - "members": [ - { - "astId": 18464, - "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", - "label": "kind", - "offset": 0, - "slot": "0", - "type": "t_enum(SupplyKind)18472" - }, - { - "astId": 18467, - "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", - "label": "tokenAddress", - "offset": 1, - "slot": "0", - "type": "t_address" - } - ], - "numberOfBytes": "32" - }, - "t_struct(Validator)18451_storage": { + "t_struct(Validator)18966_storage": { "encoding": "inplace", "label": "struct Validator", "members": [ { - "astId": 18446, + "astId": 18961, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "weight", "offset": 0, @@ -811,7 +819,7 @@ "type": "t_uint256" }, { - "astId": 18448, + "astId": 18963, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "addr", "offset": 0, @@ -819,7 +827,7 @@ "type": "t_address" }, { - "astId": 18450, + "astId": 18965, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "metadata", "offset": 0, @@ -829,12 +837,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ValidatorInfo)18392_storage": { + "t_struct(ValidatorInfo)18907_storage": { "encoding": "inplace", "label": "struct ValidatorInfo", "members": [ { - "astId": 18384, + "astId": 18899, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "federatedPower", "offset": 0, @@ -842,7 +850,7 @@ "type": "t_uint256" }, { - "astId": 18386, + "astId": 18901, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "confirmedCollateral", "offset": 0, @@ -850,7 +858,7 @@ "type": "t_uint256" }, { - "astId": 18388, + "astId": 18903, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "totalCollateral", "offset": 0, @@ -858,7 +866,7 @@ "type": "t_uint256" }, { - "astId": 18391, + "astId": 18906, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "metadata", "offset": 0, @@ -868,20 +876,20 @@ ], "numberOfBytes": "128" }, - "t_struct(ValidatorSet)18427_storage": { + "t_struct(ValidatorSet)18942_storage": { "encoding": "inplace", "label": "struct ValidatorSet", "members": [ { - "astId": 18406, + "astId": 18921, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "permissionMode", "offset": 0, "slot": "0", - "type": "t_enum(PermissionMode)18397" + "type": "t_enum(PermissionMode)18912" }, { - "astId": 18409, + "astId": 18924, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "activeLimit", "offset": 1, @@ -889,7 +897,7 @@ "type": "t_uint16" }, { - "astId": 18412, + "astId": 18927, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "totalConfirmedCollateral", "offset": 0, @@ -897,28 +905,28 @@ "type": "t_uint256" }, { - "astId": 18418, + "astId": 18933, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "validators", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(ValidatorInfo)18392_storage)" + "type": "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)" }, { - "astId": 18422, + "astId": 18937, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "activeValidators", "offset": 0, "slot": "3", - "type": "t_struct(MinPQ)17228_storage" + "type": "t_struct(MinPQ)17743_storage" }, { - "astId": 18426, + "astId": 18941, "contract": "contracts/SubnetActorDiamond.sol:SubnetActorDiamond", "label": "waitingValidators", "offset": 0, "slot": "6", - "type": "t_struct(MaxPQ)16610_storage" + "type": "t_struct(MaxPQ)17125_storage" } ], "numberOfBytes": "288" diff --git a/contracts/.storage-layouts/SubnetActorModifiers.json b/contracts/.storage-layouts/SubnetActorModifiers.json index 2a69ed5532..dee7289072 100644 --- a/contracts/.storage-layouts/SubnetActorModifiers.json +++ b/contracts/.storage-layouts/SubnetActorModifiers.json @@ -1,12 +1,12 @@ { "storage": [ { - "astId": 15353, + "astId": 16393, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "s", "offset": 0, "slot": "0", - "type": "t_struct(SubnetActorStorage)15339_storage" + "type": "t_struct(SubnetActorStorage)16379_storage" } ], "types": { @@ -27,14 +27,14 @@ "label": "bytes32[]", "numberOfBytes": "32" }, - "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage": { - "base": "t_struct(IpcEnvelope)18187_storage", + "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage": { + "base": "t_struct(IpcEnvelope)18702_storage", "encoding": "dynamic_array", "label": "struct IpcEnvelope[]", "numberOfBytes": "32" }, - "t_array(t_struct(Validator)18451_storage)dyn_storage": { - "base": "t_struct(Validator)18451_storage", + "t_array(t_struct(Validator)18966_storage)dyn_storage": { + "base": "t_struct(Validator)18966_storage", "encoding": "dynamic_array", "label": "struct Validator[]", "numberOfBytes": "32" @@ -54,31 +54,31 @@ "label": "bytes", "numberOfBytes": "32" }, - "t_enum(ConsensusType)5472": { + "t_enum(AssetKind)18987": { + "encoding": "inplace", + "label": "enum AssetKind", + "numberOfBytes": "1" + }, + "t_enum(ConsensusType)5500": { "encoding": "inplace", "label": "enum ConsensusType", "numberOfBytes": "1" }, - "t_enum(IpcMsgKind)18164": { + "t_enum(IpcMsgKind)18679": { "encoding": "inplace", "label": "enum IpcMsgKind", "numberOfBytes": "1" }, - "t_enum(PermissionMode)18397": { + "t_enum(PermissionMode)18912": { "encoding": "inplace", "label": "enum PermissionMode", "numberOfBytes": "1" }, - "t_enum(StakingOperation)18320": { + "t_enum(StakingOperation)18835": { "encoding": "inplace", "label": "enum StakingOperation", "numberOfBytes": "1" }, - "t_enum(SupplyKind)18472": { - "encoding": "inplace", - "label": "enum SupplyKind", - "numberOfBytes": "1" - }, "t_int8": { "encoding": "inplace", "label": "int8", @@ -91,19 +91,19 @@ "numberOfBytes": "32", "value": "t_string_storage" }, - "t_mapping(t_address,t_struct(AddressStakingReleases)18369_storage)": { + "t_mapping(t_address,t_struct(AddressStakingReleases)18884_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct AddressStakingReleases)", "numberOfBytes": "32", - "value": "t_struct(AddressStakingReleases)18369_storage" + "value": "t_struct(AddressStakingReleases)18884_storage" }, - "t_mapping(t_address,t_struct(ValidatorInfo)18392_storage)": { + "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ValidatorInfo)", "numberOfBytes": "32", - "value": "t_struct(ValidatorInfo)18392_storage" + "value": "t_struct(ValidatorInfo)18907_storage" }, "t_mapping(t_address,t_uint16)": { "encoding": "mapping", @@ -133,26 +133,26 @@ "numberOfBytes": "32", "value": "t_address" }, - "t_mapping(t_uint16,t_struct(StakingRelease)18358_storage)": { + "t_mapping(t_uint16,t_struct(StakingRelease)18873_storage)": { "encoding": "mapping", "key": "t_uint16", "label": "mapping(uint16 => struct StakingRelease)", "numberOfBytes": "32", - "value": "t_struct(StakingRelease)18358_storage" + "value": "t_struct(StakingRelease)18873_storage" }, - "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18139_storage)": { + "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct BottomUpCheckpoint)", "numberOfBytes": "32", - "value": "t_struct(BottomUpCheckpoint)18139_storage" + "value": "t_struct(BottomUpCheckpoint)18654_storage" }, - "t_mapping(t_uint64,t_struct(StakingChange)18329_storage)": { + "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)": { "encoding": "mapping", "key": "t_uint64", "label": "mapping(uint64 => struct StakingChange)", "numberOfBytes": "32", - "value": "t_struct(StakingChange)18329_storage" + "value": "t_struct(StakingChange)18844_storage" }, "t_string_storage": { "encoding": "bytes", @@ -174,12 +174,12 @@ ], "numberOfBytes": "64" }, - "t_struct(AddressStakingReleases)18369_storage": { + "t_struct(AddressStakingReleases)18884_storage": { "encoding": "inplace", "label": "struct AddressStakingReleases", "members": [ { - "astId": 18361, + "astId": 18876, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "length", "offset": 0, @@ -187,7 +187,7 @@ "type": "t_uint16" }, { - "astId": 18363, + "astId": 18878, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "startIdx", "offset": 2, @@ -195,30 +195,53 @@ "type": "t_uint16" }, { - "astId": 18368, + "astId": 18883, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "releases", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint16,t_struct(StakingRelease)18358_storage)" + "type": "t_mapping(t_uint16,t_struct(StakingRelease)18873_storage)" } ], "numberOfBytes": "64" }, - "t_struct(BottomUpCheckpoint)18139_storage": { + "t_struct(Asset)18983_storage": { + "encoding": "inplace", + "label": "struct Asset", + "members": [ + { + "astId": 18979, + "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", + "label": "kind", + "offset": 0, + "slot": "0", + "type": "t_enum(AssetKind)18987" + }, + { + "astId": 18982, + "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", + "label": "tokenAddress", + "offset": 1, + "slot": "0", + "type": "t_address" + } + ], + "numberOfBytes": "32" + }, + "t_struct(BottomUpCheckpoint)18654_storage": { "encoding": "inplace", "label": "struct BottomUpCheckpoint", "members": [ { - "astId": 18124, + "astId": 18639, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "subnetID", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18127, + "astId": 18642, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "blockHeight", "offset": 0, @@ -226,7 +249,7 @@ "type": "t_uint256" }, { - "astId": 18130, + "astId": 18645, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "blockHash", "offset": 0, @@ -234,7 +257,7 @@ "type": "t_bytes32" }, { - "astId": 18133, + "astId": 18648, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "nextConfigurationNumber", "offset": 0, @@ -242,22 +265,22 @@ "type": "t_uint64" }, { - "astId": 18138, + "astId": 18653, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "msgs", "offset": 0, "slot": "5", - "type": "t_array(t_struct(IpcEnvelope)18187_storage)dyn_storage" + "type": "t_array(t_struct(IpcEnvelope)18702_storage)dyn_storage" } ], "numberOfBytes": "192" }, - "t_struct(FvmAddress)18218_storage": { + "t_struct(FvmAddress)18733_storage": { "encoding": "inplace", "label": "struct FvmAddress", "members": [ { - "astId": 18215, + "astId": 18730, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "addrType", "offset": 0, @@ -265,7 +288,7 @@ "type": "t_uint8" }, { - "astId": 18217, + "astId": 18732, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "payload", "offset": 0, @@ -275,59 +298,59 @@ ], "numberOfBytes": "64" }, - "t_struct(IPCAddress)18443_storage": { + "t_struct(IPCAddress)18958_storage": { "encoding": "inplace", "label": "struct IPCAddress", "members": [ { - "astId": 18439, + "astId": 18954, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "subnetId", "offset": 0, "slot": "0", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 18442, + "astId": 18957, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "rawAddress", "offset": 0, "slot": "2", - "type": "t_struct(FvmAddress)18218_storage" + "type": "t_struct(FvmAddress)18733_storage" } ], "numberOfBytes": "128" }, - "t_struct(IpcEnvelope)18187_storage": { + "t_struct(IpcEnvelope)18702_storage": { "encoding": "inplace", "label": "struct IpcEnvelope", "members": [ { - "astId": 18169, + "astId": 18684, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "kind", "offset": 0, "slot": "0", - "type": "t_enum(IpcMsgKind)18164" + "type": "t_enum(IpcMsgKind)18679" }, { - "astId": 18173, + "astId": 18688, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "to", "offset": 0, "slot": "1", - "type": "t_struct(IPCAddress)18443_storage" + "type": "t_struct(IPCAddress)18958_storage" }, { - "astId": 18177, + "astId": 18692, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "from", "offset": 0, "slot": "5", - "type": "t_struct(IPCAddress)18443_storage" + "type": "t_struct(IPCAddress)18958_storage" }, { - "astId": 18180, + "astId": 18695, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "nonce", "offset": 0, @@ -335,7 +358,7 @@ "type": "t_uint64" }, { - "astId": 18183, + "astId": 18698, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "value", "offset": 0, @@ -343,7 +366,7 @@ "type": "t_uint256" }, { - "astId": 18186, + "astId": 18701, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "message", "offset": 0, @@ -353,42 +376,42 @@ ], "numberOfBytes": "384" }, - "t_struct(MaxPQ)16610_storage": { + "t_struct(MaxPQ)17125_storage": { "encoding": "inplace", "label": "struct MaxPQ", "members": [ { - "astId": 16609, + "astId": 17124, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)17858_storage" + "type": "t_struct(PQ)18373_storage" } ], "numberOfBytes": "96" }, - "t_struct(MinPQ)17228_storage": { + "t_struct(MinPQ)17743_storage": { "encoding": "inplace", "label": "struct MinPQ", "members": [ { - "astId": 17227, + "astId": 17742, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "inner", "offset": 0, "slot": "0", - "type": "t_struct(PQ)17858_storage" + "type": "t_struct(PQ)18373_storage" } ], "numberOfBytes": "96" }, - "t_struct(PQ)17858_storage": { + "t_struct(PQ)18373_storage": { "encoding": "inplace", "label": "struct PQ", "members": [ { - "astId": 17847, + "astId": 18362, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "size", "offset": 0, @@ -396,7 +419,7 @@ "type": "t_uint16" }, { - "astId": 17852, + "astId": 18367, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "addressToPos", "offset": 0, @@ -404,7 +427,7 @@ "type": "t_mapping(t_address,t_uint16)" }, { - "astId": 17857, + "astId": 18372, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "posToAddress", "offset": 0, @@ -437,20 +460,20 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingChange)18329_storage": { + "t_struct(StakingChange)18844_storage": { "encoding": "inplace", "label": "struct StakingChange", "members": [ { - "astId": 18324, + "astId": 18839, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "op", "offset": 0, "slot": "0", - "type": "t_enum(StakingOperation)18320" + "type": "t_enum(StakingOperation)18835" }, { - "astId": 18326, + "astId": 18841, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "payload", "offset": 0, @@ -458,7 +481,7 @@ "type": "t_bytes_storage" }, { - "astId": 18328, + "astId": 18843, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "validator", "offset": 0, @@ -468,12 +491,12 @@ ], "numberOfBytes": "96" }, - "t_struct(StakingChangeLog)18350_storage": { + "t_struct(StakingChangeLog)18865_storage": { "encoding": "inplace", "label": "struct StakingChangeLog", "members": [ { - "astId": 18340, + "astId": 18855, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "nextConfigurationNumber", "offset": 0, @@ -481,7 +504,7 @@ "type": "t_uint64" }, { - "astId": 18343, + "astId": 18858, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "startConfigurationNumber", "offset": 8, @@ -489,22 +512,22 @@ "type": "t_uint64" }, { - "astId": 18349, + "astId": 18864, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "changes", "offset": 0, "slot": "1", - "type": "t_mapping(t_uint64,t_struct(StakingChange)18329_storage)" + "type": "t_mapping(t_uint64,t_struct(StakingChange)18844_storage)" } ], "numberOfBytes": "64" }, - "t_struct(StakingRelease)18358_storage": { + "t_struct(StakingRelease)18873_storage": { "encoding": "inplace", "label": "struct StakingRelease", "members": [ { - "astId": 18354, + "astId": 18869, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "releaseAt", "offset": 0, @@ -512,7 +535,7 @@ "type": "t_uint256" }, { - "astId": 18357, + "astId": 18872, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "amount", "offset": 0, @@ -522,12 +545,12 @@ ], "numberOfBytes": "64" }, - "t_struct(StakingReleaseQueue)18380_storage": { + "t_struct(StakingReleaseQueue)18895_storage": { "encoding": "inplace", "label": "struct StakingReleaseQueue", "members": [ { - "astId": 18373, + "astId": 18888, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "lockingDuration", "offset": 0, @@ -535,22 +558,22 @@ "type": "t_uint256" }, { - "astId": 18379, + "astId": 18894, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "releases", "offset": 0, "slot": "1", - "type": "t_mapping(t_address,t_struct(AddressStakingReleases)18369_storage)" + "type": "t_mapping(t_address,t_struct(AddressStakingReleases)18884_storage)" } ], "numberOfBytes": "64" }, - "t_struct(SubnetActorStorage)15339_storage": { + "t_struct(SubnetActorStorage)16379_storage": { "encoding": "inplace", "label": "struct SubnetActorStorage", "members": [ { - "astId": 15250, + "astId": 16286, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "genesisCircSupply", "offset": 0, @@ -558,7 +581,7 @@ "type": "t_uint256" }, { - "astId": 15253, + "astId": 16289, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "lastBottomUpCheckpointHeight", "offset": 0, @@ -566,7 +589,7 @@ "type": "t_uint256" }, { - "astId": 15256, + "astId": 16292, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "minActivationCollateral", "offset": 0, @@ -574,7 +597,7 @@ "type": "t_uint256" }, { - "astId": 15259, + "astId": 16295, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "bottomUpCheckPeriod", "offset": 0, @@ -582,7 +605,7 @@ "type": "t_uint256" }, { - "astId": 15261, + "astId": 16297, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "currentSubnetHash", "offset": 0, @@ -590,7 +613,7 @@ "type": "t_bytes32" }, { - "astId": 15264, + "astId": 16300, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "ipcGatewayAddr", "offset": 0, @@ -598,7 +621,7 @@ "type": "t_address" }, { - "astId": 15267, + "astId": 16303, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "maxMsgsPerBottomUpBatch", "offset": 20, @@ -606,7 +629,7 @@ "type": "t_uint64" }, { - "astId": 15270, + "astId": 16306, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "majorityPercentage", "offset": 28, @@ -614,7 +637,7 @@ "type": "t_uint8" }, { - "astId": 15273, + "astId": 16309, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "powerScale", "offset": 29, @@ -622,15 +645,15 @@ "type": "t_int8" }, { - "astId": 15277, + "astId": 16313, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "consensus", "offset": 30, "slot": "5", - "type": "t_enum(ConsensusType)5472" + "type": "t_enum(ConsensusType)5500" }, { - "astId": 15280, + "astId": 16316, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "bootstrapped", "offset": 31, @@ -638,7 +661,7 @@ "type": "t_bool" }, { - "astId": 15283, + "astId": 16319, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "minValidators", "offset": 0, @@ -646,7 +669,7 @@ "type": "t_uint64" }, { - "astId": 15286, + "astId": 16322, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "killed", "offset": 8, @@ -654,110 +677,118 @@ "type": "t_bool" }, { - "astId": 15290, + "astId": 16326, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "supplySource", "offset": 0, "slot": "7", - "type": "t_struct(SupplySource)18468_storage" + "type": "t_struct(Asset)18983_storage" }, { - "astId": 15294, + "astId": 16330, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", - "label": "parentId", + "label": "collateralSource", "offset": 0, "slot": "8", - "type": "t_struct(SubnetID)18299_storage" + "type": "t_struct(Asset)18983_storage" + }, + { + "astId": 16334, + "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", + "label": "parentId", + "offset": 0, + "slot": "9", + "type": "t_struct(SubnetID)18814_storage" }, { - "astId": 15298, + "astId": 16338, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "validatorSet", "offset": 0, - "slot": "10", - "type": "t_struct(ValidatorSet)18427_storage" + "slot": "11", + "type": "t_struct(ValidatorSet)18942_storage" }, { - "astId": 15302, + "astId": 16342, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "changeSet", "offset": 0, - "slot": "19", - "type": "t_struct(StakingChangeLog)18350_storage" + "slot": "20", + "type": "t_struct(StakingChangeLog)18865_storage" }, { - "astId": 15306, + "astId": 16346, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "releaseQueue", "offset": 0, - "slot": "21", - "type": "t_struct(StakingReleaseQueue)18380_storage" + "slot": "22", + "type": "t_struct(StakingReleaseQueue)18895_storage" }, { - "astId": 15311, + "astId": 16351, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "bootstrapNodes", "offset": 0, - "slot": "23", + "slot": "24", "type": "t_mapping(t_address,t_string_storage)" }, { - "astId": 15315, + "astId": 16355, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "bootstrapOwners", "offset": 0, - "slot": "24", + "slot": "25", "type": "t_struct(AddressSet)3459_storage" }, { - "astId": 15321, + "astId": 16361, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "committedCheckpoints", "offset": 0, - "slot": "26", - "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18139_storage)" + "slot": "27", + "type": "t_mapping(t_uint256,t_struct(BottomUpCheckpoint)18654_storage)" }, { - "astId": 15326, + "astId": 16366, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "genesisValidators", "offset": 0, - "slot": "27", - "type": "t_array(t_struct(Validator)18451_storage)dyn_storage" + "slot": "28", + "type": "t_array(t_struct(Validator)18966_storage)dyn_storage" }, { - "astId": 15331, + "astId": 16371, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "genesisBalance", "offset": 0, - "slot": "28", + "slot": "29", "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 15335, + "astId": 16375, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "genesisBalanceKeys", "offset": 0, - "slot": "29", + "slot": "30", "type": "t_array(t_address)dyn_storage" }, { - "astId": 15338, + "astId": 16378, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "validatorGater", "offset": 0, - "slot": "30", + "slot": "31", "type": "t_address" } ], - "numberOfBytes": "992" + "numberOfBytes": "1024" }, - "t_struct(SubnetID)18299_storage": { + "t_struct(SubnetID)18814_storage": { "encoding": "inplace", "label": "struct SubnetID", "members": [ { - "astId": 18294, + "astId": 18809, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "root", "offset": 0, @@ -765,7 +796,7 @@ "type": "t_uint64" }, { - "astId": 18298, + "astId": 18813, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "route", "offset": 0, @@ -775,35 +806,12 @@ ], "numberOfBytes": "64" }, - "t_struct(SupplySource)18468_storage": { - "encoding": "inplace", - "label": "struct SupplySource", - "members": [ - { - "astId": 18464, - "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", - "label": "kind", - "offset": 0, - "slot": "0", - "type": "t_enum(SupplyKind)18472" - }, - { - "astId": 18467, - "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", - "label": "tokenAddress", - "offset": 1, - "slot": "0", - "type": "t_address" - } - ], - "numberOfBytes": "32" - }, - "t_struct(Validator)18451_storage": { + "t_struct(Validator)18966_storage": { "encoding": "inplace", "label": "struct Validator", "members": [ { - "astId": 18446, + "astId": 18961, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "weight", "offset": 0, @@ -811,7 +819,7 @@ "type": "t_uint256" }, { - "astId": 18448, + "astId": 18963, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "addr", "offset": 0, @@ -819,7 +827,7 @@ "type": "t_address" }, { - "astId": 18450, + "astId": 18965, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "metadata", "offset": 0, @@ -829,12 +837,12 @@ ], "numberOfBytes": "96" }, - "t_struct(ValidatorInfo)18392_storage": { + "t_struct(ValidatorInfo)18907_storage": { "encoding": "inplace", "label": "struct ValidatorInfo", "members": [ { - "astId": 18384, + "astId": 18899, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "federatedPower", "offset": 0, @@ -842,7 +850,7 @@ "type": "t_uint256" }, { - "astId": 18386, + "astId": 18901, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "confirmedCollateral", "offset": 0, @@ -850,7 +858,7 @@ "type": "t_uint256" }, { - "astId": 18388, + "astId": 18903, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "totalCollateral", "offset": 0, @@ -858,7 +866,7 @@ "type": "t_uint256" }, { - "astId": 18391, + "astId": 18906, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "metadata", "offset": 0, @@ -868,20 +876,20 @@ ], "numberOfBytes": "128" }, - "t_struct(ValidatorSet)18427_storage": { + "t_struct(ValidatorSet)18942_storage": { "encoding": "inplace", "label": "struct ValidatorSet", "members": [ { - "astId": 18406, + "astId": 18921, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "permissionMode", "offset": 0, "slot": "0", - "type": "t_enum(PermissionMode)18397" + "type": "t_enum(PermissionMode)18912" }, { - "astId": 18409, + "astId": 18924, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "activeLimit", "offset": 1, @@ -889,7 +897,7 @@ "type": "t_uint16" }, { - "astId": 18412, + "astId": 18927, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "totalConfirmedCollateral", "offset": 0, @@ -897,28 +905,28 @@ "type": "t_uint256" }, { - "astId": 18418, + "astId": 18933, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "validators", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(ValidatorInfo)18392_storage)" + "type": "t_mapping(t_address,t_struct(ValidatorInfo)18907_storage)" }, { - "astId": 18422, + "astId": 18937, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "activeValidators", "offset": 0, "slot": "3", - "type": "t_struct(MinPQ)17228_storage" + "type": "t_struct(MinPQ)17743_storage" }, { - "astId": 18426, + "astId": 18941, "contract": "contracts/lib/LibSubnetActorStorage.sol:SubnetActorModifiers", "label": "waitingValidators", "offset": 0, "slot": "6", - "type": "t_struct(MaxPQ)16610_storage" + "type": "t_struct(MaxPQ)17125_storage" } ], "numberOfBytes": "288" diff --git a/contracts/contracts/SubnetActorDiamond.sol b/contracts/contracts/SubnetActorDiamond.sol index b080d7d991..5abb6cfb32 100644 --- a/contracts/contracts/SubnetActorDiamond.sol +++ b/contracts/contracts/SubnetActorDiamond.sol @@ -10,18 +10,18 @@ import {IERC165} from "./interfaces/IERC165.sol"; import {GatewayCannotBeZero, NotGateway, InvalidSubmissionPeriod, InvalidCollateral, InvalidMajorityPercentage, InvalidPowerScale} from "./errors/IPCErrors.sol"; import {BATCH_PERIOD, MAX_MSGS_PER_BATCH} from "./structs/CrossNet.sol"; import {LibDiamond} from "./lib/LibDiamond.sol"; -import {PermissionMode, SubnetID, SupplyKind, SupplySource} from "./structs/Subnet.sol"; +import {PermissionMode, SubnetID, AssetKind, Asset} from "./structs/Subnet.sol"; import {SubnetIDHelper} from "./lib/SubnetIDHelper.sol"; import {LibStaking} from "./lib/LibStaking.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {SupplySourceHelper} from "./lib/SupplySourceHelper.sol"; +import {AssetHelper} from "./lib/AssetHelper.sol"; error FunctionNotFound(bytes4 _functionSelector); contract SubnetActorDiamond { SubnetActorStorage internal s; using SubnetIDHelper for SubnetID; - using SupplySourceHelper for SupplySource; + using AssetHelper for Asset; struct ConstructorParams { uint256 minActivationCollateral; @@ -33,7 +33,8 @@ contract SubnetActorDiamond { ConsensusType consensus; int8 powerScale; PermissionMode permissionMode; - SupplySource supplySource; + Asset supplySource; + Asset collateralSource; SubnetID parentId; address validatorGater; } @@ -96,6 +97,7 @@ contract SubnetActorDiamond { s.changeSet.startConfigurationNumber = LibStaking.INITIAL_CONFIGURATION_NUMBER; // Set the supply strategy. s.supplySource = params.supplySource; + s.collateralSource = params.collateralSource; if (params.validatorGater != address(0)) { s.validatorGater = params.validatorGater; diff --git a/contracts/contracts/gateway/GatewayManagerFacet.sol b/contracts/contracts/gateway/GatewayManagerFacet.sol index 7fd9636e6f..52b743593a 100644 --- a/contracts/contracts/gateway/GatewayManagerFacet.sol +++ b/contracts/contracts/gateway/GatewayManagerFacet.sol @@ -6,8 +6,8 @@ import {SubnetActorGetterFacet} from "../subnet/SubnetActorGetterFacet.sol"; import {BURNT_FUNDS_ACTOR} from "../constants/Constants.sol"; import {IpcEnvelope} from "../structs/CrossNet.sol"; import {FvmAddress} from "../structs/FvmAddress.sol"; -import {SubnetID, Subnet, SupplySource} from "../structs/Subnet.sol"; -import {Membership, SupplyKind} from "../structs/Subnet.sol"; +import {SubnetID, Subnet, Asset} from "../structs/Subnet.sol"; +import {Membership, AssetKind} from "../structs/Subnet.sol"; import {AlreadyRegisteredSubnet, CannotReleaseZero, MethodNotAllowed, NotEnoughFunds, NotEnoughFundsToRelease, NotEnoughCollateral, NotEmptySubnetCircSupply, NotRegisteredSubnet, InvalidXnetMessage, InvalidXnetMessageReason} from "../errors/IPCErrors.sol"; import {LibGateway} from "../lib/LibGateway.sol"; import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; @@ -16,7 +16,7 @@ import {FilAddress} from "fevmate/contracts/utils/FilAddress.sol"; import {ReentrancyGuard} from "../lib/LibReentrancyGuard.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; -import {SupplySourceHelper} from "../lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../lib/AssetHelper.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; string constant ERR_CHILD_SUBNET_NOT_ALLOWED = "Subnet does not allow child subnets"; @@ -24,23 +24,26 @@ string constant ERR_CHILD_SUBNET_NOT_ALLOWED = "Subnet does not allow child subn contract GatewayManagerFacet is GatewayActorModifiers, ReentrancyGuard { using FilAddress for address payable; using SubnetIDHelper for SubnetID; - using SupplySourceHelper for SupplySource; + using AssetHelper for Asset; using EnumerableSet for EnumerableSet.Bytes32Set; /// @notice register a subnet in the gateway. It is called by a subnet when it reaches the threshold stake /// @dev The subnet can optionally pass a genesis circulating supply that would be pre-allocated in the /// subnet from genesis (without having to wait for the subnet to be spawned to propagate the funds). - function register(uint256 genesisCircSupply) external payable { + function register(uint256 genesisCircSupply, uint256 collateral) external payable { // If L2+ support is not enabled, only allow the registration of new // subnets in the root if (s.networkName.route.length + 1 >= s.maxTreeDepth) { revert MethodNotAllowed(ERR_CHILD_SUBNET_NOT_ALLOWED); } - if (msg.value < genesisCircSupply) { - revert NotEnoughFunds(); + if (genesisCircSupply > 0) { + SubnetActorGetterFacet(msg.sender).supplySource().lock(genesisCircSupply); + } + if (collateral > 0) { + SubnetActorGetterFacet(msg.sender).collateralSource().lock(collateral); } - uint256 collateral = msg.value - genesisCircSupply; + SubnetID memory subnetId = s.networkName.createSubnetId(msg.sender); (bool registered, Subnet storage subnet) = LibGateway.getSubnet(subnetId); @@ -58,18 +61,23 @@ contract GatewayManagerFacet is GatewayActorModifiers, ReentrancyGuard { } /// @notice addStake - add collateral for an existing subnet - function addStake() external payable { - if (msg.value == 0) { + function addStake(uint256 amount) external payable { + if (amount == 0) { revert NotEnoughFunds(); } + // The fund flow for stake is from Validator -> SubnetActor -> Gateway. + // Because msg.sender is actually the subnet actor, this method sends the fund from + // the subnet actor caller the gateway. + SubnetActorGetterFacet(msg.sender).collateralSource().lock(amount); + (bool registered, Subnet storage subnet) = LibGateway.getSubnet(msg.sender); if (!registered) { revert NotRegisteredSubnet(); } - subnet.stake += msg.value; + subnet.stake += amount; } /// @notice release collateral for an existing subnet. @@ -91,7 +99,10 @@ contract GatewayManagerFacet is GatewayActorModifiers, ReentrancyGuard { subnet.stake -= amount; - payable(subnet.id.getActor()).sendValue(amount); + // Release fund flows from Gateway -> SubnetActor -> ReleaseQueue (Locking) -> Validator. + // Because msg.sender is actually the subnet actor, this method sends the fund back to + // the subnet actor caller. + SubnetActorGetterFacet(msg.sender).collateralSource().transferFunds(payable(msg.sender), amount); } /// @notice kill an existing subnet. @@ -114,8 +125,7 @@ contract GatewayManagerFacet is GatewayActorModifiers, ReentrancyGuard { delete s.subnets[id]; s.subnetKeys.remove(id); - - payable(msg.sender).sendValue(stake); + SubnetActorGetterFacet(msg.sender).collateralSource().transferFunds(payable(msg.sender), stake); } /// @notice credits the received value to the specified address in the specified child subnet. @@ -137,8 +147,8 @@ contract GatewayManagerFacet is GatewayActorModifiers, ReentrancyGuard { } // Validate that the supply strategy is native. - SupplySource memory supplySource = SubnetActorGetterFacet(subnetId.getActor()).supplySource(); - supplySource.expect(SupplyKind.Native); + Asset memory supplySource = SubnetActorGetterFacet(subnetId.getActor()).supplySource(); + supplySource.expect(AssetKind.Native); IpcEnvelope memory crossMsg = CrossMsgHelper.createFundMsg({ subnet: subnetId, @@ -172,8 +182,8 @@ contract GatewayManagerFacet is GatewayActorModifiers, ReentrancyGuard { // Check that the supply strategy is ERC20. // There is no need to check whether the subnet exists. If it doesn't exist, the call to getter will revert. // LibGateway.commitTopDownMsg will also revert if the subnet doesn't exist. - SupplySource memory supplySource = SubnetActorGetterFacet(subnetId.getActor()).supplySource(); - supplySource.expect(SupplyKind.ERC20); + Asset memory supplySource = SubnetActorGetterFacet(subnetId.getActor()).supplySource(); + supplySource.expect(AssetKind.ERC20); // Locks a specified amount into custody, adjusting for tokens with transfer fees. This operation // accommodates inflationary tokens, potentially reflecting a higher effective locked amount. diff --git a/contracts/contracts/gateway/GatewayMessengerFacet.sol b/contracts/contracts/gateway/GatewayMessengerFacet.sol index 4739b4eb74..472f9763e6 100644 --- a/contracts/contracts/gateway/GatewayMessengerFacet.sol +++ b/contracts/contracts/gateway/GatewayMessengerFacet.sol @@ -4,12 +4,12 @@ pragma solidity ^0.8.23; import {GatewayActorModifiers} from "../lib/LibGatewayActorStorage.sol"; import {IpcEnvelope, CallMsg, IpcMsgKind} from "../structs/CrossNet.sol"; import {IPCMsgType} from "../enums/IPCMsgType.sol"; -import {SubnetID, SupplyKind, IPCAddress} from "../structs/Subnet.sol"; +import {SubnetID, AssetKind, IPCAddress} from "../structs/Subnet.sol"; import {InvalidXnetMessage, InvalidXnetMessageReason, CannotSendCrossMsgToItself, MethodNotAllowed} from "../errors/IPCErrors.sol"; import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; import {LibGateway} from "../lib/LibGateway.sol"; import {FilAddress} from "fevmate/contracts/utils/FilAddress.sol"; -import {SupplySourceHelper} from "../lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../lib/AssetHelper.sol"; import {CrossMsgHelper} from "../lib/CrossMsgHelper.sol"; import {FvmAddressHelper} from "../lib/FvmAddressHelper.sol"; diff --git a/contracts/contracts/gateway/router/XnetMessagingFacet.sol b/contracts/contracts/gateway/router/XnetMessagingFacet.sol index 9504def4fd..c7e3c2a7ee 100644 --- a/contracts/contracts/gateway/router/XnetMessagingFacet.sol +++ b/contracts/contracts/gateway/router/XnetMessagingFacet.sol @@ -11,15 +11,15 @@ import {Subnet} from "../../structs/Subnet.sol"; import {FilAddress} from "fevmate/contracts/utils/FilAddress.sol"; import {SubnetIDHelper} from "../../lib/SubnetIDHelper.sol"; import {CrossMsgHelper} from "../../lib/CrossMsgHelper.sol"; -import {SupplySourceHelper} from "../../lib/SupplySourceHelper.sol"; -import {SupplySource} from "../../structs/Subnet.sol"; +import {AssetHelper} from "../../lib/AssetHelper.sol"; +import {Asset} from "../../structs/Subnet.sol"; import {NotRegisteredSubnet} from "../../errors/IPCErrors.sol"; contract XnetMessagingFacet is GatewayActorModifiers { using SubnetIDHelper for SubnetID; using CrossMsgHelper for IpcEnvelope; - using SupplySourceHelper for SupplySource; + using AssetHelper for Asset; /// @notice Applies top-down cross-net messages locally. This is invoked by IPC nodes when drawing messages from /// their parent subnet for local execution. That's why the sender is restricted to the system sender, diff --git a/contracts/contracts/interfaces/IGateway.sol b/contracts/contracts/interfaces/IGateway.sol index 7d83c9d2ef..9d820dff6a 100644 --- a/contracts/contracts/interfaces/IGateway.sol +++ b/contracts/contracts/interfaces/IGateway.sol @@ -10,10 +10,10 @@ import {FvmAddress} from "../structs/FvmAddress.sol"; interface IGateway { /// @notice Register is called by subnet actors to put the required collateral /// and register the subnet to the hierarchy. - function register(uint256 genesisCircSupply) external payable; + function register(uint256 genesisCircSupply, uint256 collateral) external payable; /// @notice AddStake adds stake to the collateral of a subnet. - function addStake() external payable; + function addStake(uint256 amount) external payable; /// @notice Release stake recovers some collateral of the subnet function releaseStake(uint256 amount) external; @@ -31,7 +31,7 @@ interface IGateway { /// This functions ends up minting supply in the subnet equal to the value of the transaction. It does so by /// committing the relevant top-down message, updating the top-down nonce along the way. /// - /// Calling this method on a subnet whose supply source is not 'native' will revert with UnexpectedSupplySource(). + /// Calling this method on a subnet whose supply source is not 'native' will revert with UnexpectedAsset(). function fund(SubnetID calldata subnetId, FvmAddress calldata to) external payable; /// @notice fundWithToken locks the specified amount of tokens in the ERC20 contract linked to the subnet, and @@ -45,7 +45,7 @@ interface IGateway { /// It's possible to call this method from an EOA or a contract. Regardless, it's recommended to approve strictly /// the amount that will subsequently be deposited into the subnet. Keeping outstanding approvals is not recommended. /// - /// Calling this method on a subnet whose supply source is not 'ERC20' will revert with UnexpectedSupplySource(). + /// Calling this method on a subnet whose supply source is not 'ERC20' will revert with UnexpectedAsset(). function fundWithToken(SubnetID calldata subnetId, FvmAddress calldata to, uint256 amount) external; /// @notice Release creates a new check message to release funds in parent chain diff --git a/contracts/contracts/lib/SupplySourceHelper.sol b/contracts/contracts/lib/AssetHelper.sol similarity index 64% rename from contracts/contracts/lib/SupplySourceHelper.sol rename to contracts/contracts/lib/AssetHelper.sol index 5c2acd7257..cdfe607dd9 100644 --- a/contracts/contracts/lib/SupplySourceHelper.sol +++ b/contracts/contracts/lib/AssetHelper.sol @@ -2,103 +2,99 @@ pragma solidity ^0.8.23; import {NotEnoughBalance} from "../errors/IPCErrors.sol"; -import {SupplySource, SupplyKind} from "../structs/Subnet.sol"; +import {Asset, AssetKind} from "../structs/Subnet.sol"; import {EMPTY_BYTES} from "../constants/Constants.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {SubnetActorGetterFacet} from "../subnet/SubnetActorGetterFacet.sol"; /// @notice Helpers to deal with a supply source. -library SupplySourceHelper { +library AssetHelper { using SafeERC20 for IERC20; - error InvalidERC20Address(); - error NoBalanceIncrease(); - error UnexpectedSupplySource(); - error UnknownSupplySource(); - /// @notice Assumes that the address provided belongs to a subnet rooted on this network, /// and checks if its supply kind matches the provided one. /// It reverts if the address does not correspond to a subnet actor. - function hasSupplyOfKind(address subnetActor, SupplyKind compare) internal view returns (bool) { + function hasSupplyOfKind(address subnetActor, AssetKind compare) internal view returns (bool) { return SubnetActorGetterFacet(subnetActor).supplySource().kind == compare; } /// @notice Checks that a given supply strategy is correctly formed and its preconditions are met. /// It reverts if conditions are not met. - function validate(SupplySource memory supplySource) internal view { - if (supplySource.kind == SupplyKind.ERC20) { - if (supplySource.tokenAddress == address(0)) { - revert InvalidERC20Address(); - } + function validate(Asset memory asset) internal view { + if (asset.kind == AssetKind.ERC20) { + require(asset.tokenAddress != address(0), "Invalid ERC20 address"); // We require that the ERC20 token contract exists beforehand. // The call to balanceOf will revert if the supplied address does not exist, or if it's not an ERC20 contract. // Ideally we'd use ERC165 to check if the contract implements the ERC20 standard, but the latter does not support supportsInterface(). - IERC20 token = IERC20(supplySource.tokenAddress); + IERC20 token = IERC20(asset.tokenAddress); token.balanceOf(address(0)); } } /// @notice Asserts that the supply strategy is of the given kind. If not, it reverts. - function expect(SupplySource memory supplySource, SupplyKind kind) internal pure { - if (supplySource.kind != kind) { - revert UnexpectedSupplySource(); - } + function expect(Asset memory asset, AssetKind kind) internal pure { + require(asset.kind == kind, "Unexpected asset"); } /// @notice Locks the specified amount from msg.sender into custody. /// Reverts with NoBalanceIncrease if the token balance does not increase. /// May return more than requested for inflationary tokens due to balance rise. - function lock(SupplySource memory supplySource, uint256 value) internal returns (uint256) { - if (supplySource.kind == SupplyKind.ERC20) { - IERC20 token = IERC20(supplySource.tokenAddress); + function lock(Asset memory asset, uint256 value) internal returns (uint256) { + if (asset.kind == AssetKind.ERC20) { + IERC20 token = IERC20(asset.tokenAddress); + + // Dealing with deflationary tokens. uint256 initialBalance = token.balanceOf(address(this)); token.safeTransferFrom({from: msg.sender, to: address(this), value: value}); uint256 finalBalance = token.balanceOf(address(this)); - if (finalBalance <= initialBalance) { - revert NoBalanceIncrease(); - } - // Safe arithmetic is not necessary because underflow is not possible due to the check above + require(finalBalance > initialBalance, "No balance increase"); + // Safe arithmetic is not necessary because underflow is not possible due to the assert above return finalBalance - initialBalance; + } else { + // Ensure we have received enough funds to cover the value. + // msg.value might have coins in excess of the amount that we need to lock (e.g. when contributing both native collateral and supply at the same time). + // That's why we can't do a strict equality check. + require(msg.value >= value, "Insufficient funds"); } // Do nothing for native. return value; } /// @notice Transfers the specified amount out of our treasury to the recipient address. - function transferFunds(SupplySource memory supplySource, + function transferFunds(Asset memory asset, address payable recipient, uint256 value ) internal returns (bool success, bytes memory ret) { - if (supplySource.kind == SupplyKind.Native) { + if (asset.kind == AssetKind.Native) { success = sendValue(payable(recipient), value); return (success, EMPTY_BYTES); - } else if (supplySource.kind == SupplyKind.ERC20) { - return ierc20Transfer(supplySource, recipient, value); + } else if (asset.kind == AssetKind.ERC20) { + return ierc20Transfer(asset, recipient, value); } } /// @notice Wrapper for an IERC20 transfer that bubbles up the success or failure /// and the return value instead of reverting so a cross-message receipt can be /// triggered from the execution. - /// This function the `safeTransfer` function used before. + /// This function is the same as `safeTransfer` function used before. function ierc20Transfer( - SupplySource memory supplySource, + Asset memory asset, address recipient, uint256 value ) internal returns (bool success, bytes memory ret) { return - supplySource.tokenAddress.call( - // using IERC20 transfer instead of safe transfer so we can - // bubble-up the failure instead of reverting on failure so we - // can send the receipt. - abi.encodePacked(IERC20.transfer.selector, abi.encode(recipient, value)) - ); + asset.tokenAddress.call( + // using IERC20 transfer instead of safe transfer so we can + // bubble-up the failure instead of reverting on failure so we + // can send the receipt. + abi.encodePacked(IERC20.transfer.selector, abi.encode(recipient, value)) + ); } /// @notice Calls the target with the specified data, ensuring it receives the specified value. function performCall( - SupplySource memory supplySource, + Asset memory asset, address payable target, bytes memory data, uint256 value @@ -109,24 +105,24 @@ library SupplySourceHelper { } // Otherwise, we need to do something different. - if (supplySource.kind == SupplyKind.Native) { + if (asset.kind == AssetKind.Native) { // Use the optimized path to send value along with the call. (success, ret) = functionCallWithValue({target: target, data: data, value: value}); - } else if (supplySource.kind == SupplyKind.ERC20) { - (success, ret) = functionCallWithERC20Value({supplySource: supplySource, target: target, data: data, value: value}); + } else if (asset.kind == AssetKind.ERC20) { + (success, ret) = functionCallWithERC20Value({asset: asset, target: target, data: data, value: value}); } return (success, ret); } /// @dev Performs the function call with ERC20 value atomically function functionCallWithERC20Value( - SupplySource memory supplySource, + Asset memory asset, address target, bytes memory data, uint256 value ) internal returns (bool success, bytes memory ret) { // Transfer the tokens first, _then_ perform the call. - (success, ret) = ierc20Transfer(supplySource, target, value); + (success, ret) = ierc20Transfer(asset, target, value); if (success) { // Perform the call only if the ERC20 was successful. @@ -138,7 +134,7 @@ library SupplySourceHelper { if (ret.length > 0) { assembly { let returndata_size := mload(ret) - // see https://ethereum.stackexchange.com/questions/133748/trying-to-understand-solidity-assemblys-revert-function + // see https://ethereum.stackexchange.com/questions/133748/trying-to-understand-solidity-assemblys-revert-function revert(add(32, ret), returndata_size) } } @@ -187,20 +183,35 @@ library SupplySourceHelper { if (address(this).balance < value) { revert NotEnoughBalance(); } - (bool success, ) = recipient.call{value: value}(""); + (bool success,) = recipient.call{value: value}(""); return success; } /// @notice Gets the balance in our treasury. - function balance(SupplySource memory supplySource) internal view returns (uint256 ret) { - if (supplySource.kind == SupplyKind.Native) { + function balance(Asset memory asset) internal view returns (uint256 ret) { + if (asset.kind == AssetKind.Native) { ret = address(this).balance; - } else if (supplySource.kind == SupplyKind.ERC20) { - ret = IERC20(supplySource.tokenAddress).balanceOf(address(this)); + } else if (asset.kind == AssetKind.ERC20) { + ret = IERC20(asset.tokenAddress).balanceOf(address(this)); } } - function native() internal pure returns (SupplySource memory) { - return SupplySource({kind: SupplyKind.Native, tokenAddress: address(0)}); + // @notice Makes the asset available for spending by the given spender, without actually sending it. + // @return msgValue The amount of msg.value that needs to be sent along with the subsequent call that will _actually_ spend that asset. + // Will be 0 if the asset is a token, since no native coins are to be sent. + function makeAvailable(Asset memory self, address spender, uint256 amount) internal returns (uint256 msgValue) { + if (self.kind == AssetKind.Native) { + msgValue = amount; + } else if (self.kind == AssetKind.ERC20) { + IERC20 token = IERC20(self.tokenAddress); + token.safeIncreaseAllowance(spender, amount); + msgValue = 0; + } + return msgValue; + } + + function native() internal pure returns (Asset memory) { + return Asset({kind: AssetKind.Native, tokenAddress: address(0)}); } -} + +} \ No newline at end of file diff --git a/contracts/contracts/lib/CrossMsgHelper.sol b/contracts/contracts/lib/CrossMsgHelper.sol index 534a7269a4..7abe365d23 100644 --- a/contracts/contracts/lib/CrossMsgHelper.sol +++ b/contracts/contracts/lib/CrossMsgHelper.sol @@ -10,8 +10,8 @@ import {FvmAddressHelper} from "../lib/FvmAddressHelper.sol"; import {FvmAddress} from "../structs/FvmAddress.sol"; import {FilAddress} from "fevmate/contracts/utils/FilAddress.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; -import {SupplySource} from "../structs/Subnet.sol"; -import {SupplySourceHelper} from "./SupplySourceHelper.sol"; +import {Asset} from "../structs/Subnet.sol"; +import {AssetHelper} from "./AssetHelper.sol"; import {IIpcHandler} from "../../sdk/interfaces/IIpcHandler.sol"; /// @title Helper library for manipulating IpcEnvelope-related structs @@ -19,7 +19,7 @@ library CrossMsgHelper { using SubnetIDHelper for SubnetID; using FilAddress for address; using FvmAddressHelper for FvmAddress; - using SupplySourceHelper for SupplySource; + using AssetHelper for Asset; error CannotExecuteEmptyEnvelope(); @@ -154,7 +154,7 @@ library CrossMsgHelper { /// forwarded message, or the receipt in the case of failure. function execute( IpcEnvelope calldata crossMsg, - SupplySource memory supplySource + Asset memory supplySource ) public returns (bool success, bytes memory ret) { if (isEmpty(crossMsg)) { revert CannotExecuteEmptyEnvelope(); diff --git a/contracts/contracts/lib/LibGateway.sol b/contracts/contracts/lib/LibGateway.sol index 3713658a21..f7c3e84ada 100644 --- a/contracts/contracts/lib/LibGateway.sol +++ b/contracts/contracts/lib/LibGateway.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import {IPCMsgType} from "../enums/IPCMsgType.sol"; import {GatewayActorStorage, LibGatewayActorStorage} from "../lib/LibGatewayActorStorage.sol"; import {BURNT_FUNDS_ACTOR} from "../constants/Constants.sol"; -import {SubnetID, Subnet, SupplyKind, SupplySource} from "../structs/Subnet.sol"; +import {SubnetID, Subnet, AssetKind, Asset} from "../structs/Subnet.sol"; import {SubnetActorGetterFacet} from "../subnet/SubnetActorGetterFacet.sol"; import {CallMsg, IpcMsgKind, IpcEnvelope, OutcomeType, BottomUpMsgBatch, BottomUpMsgBatch, BottomUpCheckpoint, ParentFinality} from "../structs/CrossNet.sol"; import {Membership} from "../structs/Subnet.sol"; @@ -12,15 +12,15 @@ import {CannotSendCrossMsgToItself, MethodNotAllowed, MaxMsgsPerBatchExceeded, I import {CrossMsgHelper} from "../lib/CrossMsgHelper.sol"; import {FilAddress} from "fevmate/contracts/utils/FilAddress.sol"; import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; -import {SupplySourceHelper} from "../lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../lib/AssetHelper.sol"; library LibGateway { using SubnetIDHelper for SubnetID; using CrossMsgHelper for IpcEnvelope; - using SupplySourceHelper for address; + using AssetHelper for address; using SubnetIDHelper for SubnetID; using FilAddress for address payable; - using SupplySourceHelper for SupplySource; + using AssetHelper for Asset; event MembershipUpdated(Membership); /// @dev subnet refers to the next "down" subnet that the `envelope.message.to` should be forwarded to. @@ -365,7 +365,7 @@ library LibGateway { // The first thing we do is to find out the directionality of this message and act accordingly, // incrasing the applied nonces conveniently. // slither-disable-next-line uninitialized-local - SupplySource memory supplySource; + Asset memory supplySource; IPCMsgType applyType = crossMsg.applyType(s.networkName); if (applyType == IPCMsgType.BottomUp) { // Load the subnet this message is coming from. Ensure that it exists and that the nonce expectation is met. @@ -395,7 +395,7 @@ library LibGateway { // The value carried in top-down messages locally maps to the native coin, so we pass over the // native supply source. - supplySource = SupplySourceHelper.native(); + supplySource = AssetHelper.native(); } // If the crossnet destination is NOT the current network (network where the gateway is running), @@ -422,7 +422,7 @@ library LibGateway { /// catch contract revert messages as well. We need this because in `CrossMsgHelper.execute` /// there are `require` and `revert` calls, without reflexive call, the execution will /// revert and block the checkpoint submission process. - function executeCrossMsg(IpcEnvelope memory crossMsg, SupplySource memory supplySource) internal returns (bool success, bytes memory result) { + function executeCrossMsg(IpcEnvelope memory crossMsg, Asset memory supplySource) internal returns (bool success, bytes memory result) { (success, result) = address(CrossMsgHelper).delegatecall( // solhint-disable-line avoid-low-level-calls abi.encodeWithSelector(CrossMsgHelper.execute.selector, crossMsg, supplySource) ); @@ -499,11 +499,11 @@ library LibGateway { // We're traversing up, so if we're the first hop, we reject if the subnet was ERC20. // If we're not the first hop, a child propagated this to us, they made a mistake and // and we don't have enough info to evaluate. - reject = from.getParentSubnet().equals(s.networkName) && from.getActor().hasSupplyOfKind(SupplyKind.ERC20); + reject = from.getParentSubnet().equals(s.networkName) && from.getActor().hasSupplyOfKind(AssetKind.ERC20); } else if (applyType == IPCMsgType.TopDown) { // We're traversing down. // Check the next subnet (which can may be the destination subnet). - reject = to.down(s.networkName).getActor().hasSupplyOfKind(SupplyKind.ERC20); + reject = to.down(s.networkName).getActor().hasSupplyOfKind(AssetKind.ERC20); } if (reject) { if (crossMessage.kind == IpcMsgKind.Transfer) { diff --git a/contracts/contracts/lib/LibStaking.sol b/contracts/contracts/lib/LibStaking.sol index 5e10eeb692..cfb1f7a796 100644 --- a/contracts/contracts/lib/LibStaking.sol +++ b/contracts/contracts/lib/LibStaking.sol @@ -6,7 +6,8 @@ import {LibSubnetActorStorage, SubnetActorStorage} from "./LibSubnetActorStorage import {LibMaxPQ, MaxPQ} from "./priority/LibMaxPQ.sol"; import {LibMinPQ, MinPQ} from "./priority/LibMinPQ.sol"; import {LibStakingChangeLog} from "./LibStakingChangeLog.sol"; -import {PermissionMode, StakingReleaseQueue, StakingChangeLog, StakingChange, StakingChangeRequest, StakingOperation, StakingRelease, ValidatorSet, AddressStakingReleases, ParentValidatorsTracker, Validator} from "../structs/Subnet.sol"; +import {AssetHelper} from "./AssetHelper.sol"; +import {PermissionMode, StakingReleaseQueue, StakingChangeLog, StakingChange, StakingChangeRequest, StakingOperation, StakingRelease, ValidatorSet, AddressStakingReleases, ParentValidatorsTracker, Validator, Asset} from "../structs/Subnet.sol"; import {WithdrawExceedingCollateral, NotValidator, CannotConfirmFutureChanges, NoCollateralToWithdraw, AddressShouldBeValidator, InvalidConfigurationNumber} from "../errors/IPCErrors.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; @@ -87,8 +88,6 @@ library LibStakingReleaseQueue { delete self.releases[validator]; } - payable(validator).sendValue(amount); - return amount; } } @@ -374,6 +373,7 @@ library LibStaking { using LibStakingReleaseQueue for StakingReleaseQueue; using LibStakingChangeLog for StakingChangeLog; using LibValidatorSet for ValidatorSet; + using AssetHelper for Asset; using LibMaxPQ for MaxPQ; using LibMinPQ for MinPQ; using Address for address payable; @@ -506,9 +506,6 @@ library LibStaking { s.validatorSet.recordWithdraw(validator, amount); // confirm deposit that updates the confirmed collateral s.validatorSet.confirmWithdraw(validator, amount); - - // release stake from gateway and transfer to user - payable(validator).sendValue(amount); } // ================= Operations that are queued ============== @@ -543,9 +540,9 @@ library LibStaking { // =============== Other functions ================ /// @notice Claim the released collateral - function claimCollateral(address validator) internal { + function claimCollateral(address validator) internal returns(uint256 amount) { SubnetActorStorage storage s = LibSubnetActorStorage.appStorage(); - uint256 amount = s.releaseQueue.claim(validator); + amount = s.releaseQueue.claim(validator); emit CollateralClaimed(validator, amount); } @@ -578,14 +575,18 @@ library LibStaking { s.validatorSet.confirmFederatedPower(validator, power); } else { uint256 amount = abi.decode(change.payload, (uint256)); + address gateway = s.ipcGatewayAddr; if (change.op == StakingOperation.Withdraw) { s.validatorSet.confirmWithdraw(validator, amount); s.releaseQueue.addNewRelease(validator, amount); - IGateway(s.ipcGatewayAddr).releaseStake(amount); - } else { + IGateway(gateway).releaseStake(amount); + } else if (change.op == StakingOperation.Deposit) { s.validatorSet.confirmDeposit(validator, amount); - IGateway(s.ipcGatewayAddr).addStake{value: amount}(); + uint256 msgValue = s.collateralSource.makeAvailable(gateway, amount); + IGateway(gateway).addStake{value: msgValue}(amount); + } else { + revert("Unknown staking operation"); } } diff --git a/contracts/contracts/lib/LibSubnetActor.sol b/contracts/contracts/lib/LibSubnetActor.sol index a797367f54..14731f7685 100644 --- a/contracts/contracts/lib/LibSubnetActor.sol +++ b/contracts/contracts/lib/LibSubnetActor.sol @@ -6,16 +6,18 @@ import {ERR_PERMISSIONED_AND_BOOTSTRAPPED} from "../errors/IPCErrors.sol"; import {NotEnoughGenesisValidators, DuplicatedGenesisValidator, NotOwnerOfPublicKey, MethodNotAllowed} from "../errors/IPCErrors.sol"; import {IGateway} from "../interfaces/IGateway.sol"; import {IValidatorGater} from "../interfaces/IValidatorGater.sol"; -import {Validator, ValidatorSet, PermissionMode, SubnetID} from "../structs/Subnet.sol"; +import {Validator, ValidatorSet, PermissionMode, SubnetID, Asset} from "../structs/Subnet.sol"; import {SubnetActorModifiers} from "../lib/LibSubnetActorStorage.sol"; import {LibValidatorSet, LibStaking} from "../lib/LibStaking.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {LibSubnetActorStorage, SubnetActorStorage} from "./LibSubnetActorStorage.sol"; import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; +import {AssetHelper} from "../lib/AssetHelper.sol"; library LibSubnetActor { using EnumerableSet for EnumerableSet.AddressSet; using SubnetIDHelper for SubnetID; + using AssetHelper for Asset; event SubnetBootstrapped(Validator[]); @@ -90,7 +92,7 @@ library LibSubnetActor { emit SubnetBootstrapped(s.genesisValidators); // register adding the genesis circulating supply (if it exists) - IGateway(s.ipcGatewayAddr).register{value: totalCollateral + s.genesisCircSupply}(s.genesisCircSupply); + registerInGateway(totalCollateral); } } } @@ -151,7 +153,19 @@ library LibSubnetActor { emit SubnetBootstrapped(s.genesisValidators); // register adding the genesis circulating supply (if it exists) - IGateway(s.ipcGatewayAddr).register{value: s.genesisCircSupply}(s.genesisCircSupply); + registerInGateway(0); + } + + function registerInGateway(uint256 collateral) internal { + SubnetActorStorage storage s = LibSubnetActorStorage.appStorage(); + + uint256 genesisCircSupply = s.genesisCircSupply; + + uint256 msgValue = 0; + msgValue += s.supplySource.makeAvailable(s.ipcGatewayAddr, genesisCircSupply); + msgValue += s.collateralSource.makeAvailable(s.ipcGatewayAddr, collateral); + + IGateway(s.ipcGatewayAddr).register{value: msgValue}(genesisCircSupply, collateral); } /// @notice method that allows the contract owner to set the validators' federated power after diff --git a/contracts/contracts/lib/LibSubnetActorStorage.sol b/contracts/contracts/lib/LibSubnetActorStorage.sol index d51339a453..eaf800ca5a 100644 --- a/contracts/contracts/lib/LibSubnetActorStorage.sol +++ b/contracts/contracts/lib/LibSubnetActorStorage.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.23; import {ConsensusType} from "../enums/ConsensusType.sol"; import {NotGateway, SubnetAlreadyKilled} from "../errors/IPCErrors.sol"; import {BottomUpCheckpoint, BottomUpMsgBatchInfo} from "../structs/CrossNet.sol"; -import {SubnetID, ValidatorSet, StakingChangeLog, StakingReleaseQueue, SupplySource, Validator, PermissionMode} from "../structs/Subnet.sol"; +import {SubnetID, ValidatorSet, StakingChangeLog, StakingReleaseQueue, Asset, Validator, PermissionMode} from "../structs/Subnet.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; struct SubnetActorStorage { @@ -38,7 +38,9 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet /// @notice Determines if the subnet has been successfully killed bool killed; /// @notice subnet supply strategy. - SupplySource supplySource; + Asset supplySource; + /// @notice subnet collateral token strategy, only used for collateral based permission mode. + Asset collateralSource; /// @notice ID of the parent subnet SubnetID parentId; // =========== Staking =========== diff --git a/contracts/contracts/structs/Subnet.sol b/contracts/contracts/structs/Subnet.sol index bf7776097f..080415236a 100644 --- a/contracts/contracts/structs/Subnet.sol +++ b/contracts/contracts/structs/Subnet.sol @@ -164,16 +164,17 @@ struct Membership { uint64 configurationNumber; } -/// @notice Defines the supply source of a subnet on its parent subnet. -struct SupplySource { - /// @notice The kind of supply. - SupplyKind kind; +/// @notice Defines a more general representation of a token in subnet. Using the same set of interfaces +/// @notice for handling token operations. +struct Asset { + /// @notice The kind of token. + AssetKind kind; /// @notice The address of the ERC20 token if that supply kind is selected. address tokenAddress; } -/// @notice Determines the type of supply used by the subnet. -enum SupplyKind { +/// @notice Determines the type of the token used in the subnet. +enum AssetKind { Native, ERC20 } diff --git a/contracts/contracts/subnet/SubnetActorGetterFacet.sol b/contracts/contracts/subnet/SubnetActorGetterFacet.sol index 49778b8d2d..415064ab19 100644 --- a/contracts/contracts/subnet/SubnetActorGetterFacet.sol +++ b/contracts/contracts/subnet/SubnetActorGetterFacet.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.23; import {ConsensusType} from "../enums/ConsensusType.sol"; import {BottomUpCheckpoint, IpcEnvelope} from "../structs/CrossNet.sol"; -import {SubnetID, SupplySource} from "../structs/Subnet.sol"; +import {SubnetID, Asset} from "../structs/Subnet.sol"; import {SubnetID, ValidatorInfo, Validator, PermissionMode} from "../structs/Subnet.sol"; import {SubnetActorStorage} from "../lib/LibSubnetActorStorage.sol"; import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; @@ -213,7 +213,12 @@ contract SubnetActorGetterFacet { } /// @notice Returns the supply strategy for the subnet. - function supplySource() external view returns (SupplySource memory supply) { + function supplySource() external view returns (Asset memory supply) { return s.supplySource; } + + /// @notice Returns the collateral asset kind for the subnet. + function collateralSource() external view returns (Asset memory supply) { + return s.collateralSource; + } } diff --git a/contracts/contracts/subnet/SubnetActorManagerFacet.sol b/contracts/contracts/subnet/SubnetActorManagerFacet.sol index b0a5c835b0..1442951588 100644 --- a/contracts/contracts/subnet/SubnetActorManagerFacet.sol +++ b/contracts/contracts/subnet/SubnetActorManagerFacet.sol @@ -5,7 +5,7 @@ import {VALIDATOR_SECP256K1_PUBLIC_KEY_LENGTH} from "../constants/Constants.sol" import {ERR_VALIDATOR_JOINED, ERR_VALIDATOR_NOT_JOINED} from "../errors/IPCErrors.sol"; import {InvalidFederationPayload, SubnetAlreadyBootstrapped, NotEnoughFunds, CollateralIsZero, CannotReleaseZero, NotOwnerOfPublicKey, EmptyAddress, NotEnoughBalance, NotEnoughCollateral, NotValidator, NotAllValidatorsHaveLeft, InvalidPublicKeyLength, MethodNotAllowed, SubnetNotBootstrapped} from "../errors/IPCErrors.sol"; import {IGateway} from "../interfaces/IGateway.sol"; -import {Validator, ValidatorSet, SubnetID} from "../structs/Subnet.sol"; +import {Validator, ValidatorSet, Asset, SubnetID} from "../structs/Subnet.sol"; import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol"; import {LibDiamond} from "../lib/LibDiamond.sol"; import {ReentrancyGuard} from "../lib/LibReentrancyGuard.sol"; @@ -15,18 +15,20 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {LibSubnetActor} from "../lib/LibSubnetActor.sol"; import {Pausable} from "../lib/LibPausable.sol"; +import {AssetHelper} from "../lib/AssetHelper.sol"; contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausable { using EnumerableSet for EnumerableSet.AddressSet; using SubnetIDHelper for SubnetID; + using AssetHelper for Asset; using LibValidatorSet for ValidatorSet; using Address for address payable; /// @notice method to add some initial balance into a subnet that hasn't yet bootstrapped. /// @dev This balance is added to user addresses in genesis, and becomes part of the genesis /// circulating supply. - function preFund() external payable { - if (msg.value == 0) { + function preFund(uint256 amount) external payable { + if (amount == 0) { revert NotEnoughFunds(); } @@ -34,12 +36,14 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa revert SubnetAlreadyBootstrapped(); } + s.supplySource.lock(amount); + if (s.genesisBalance[msg.sender] == 0) { s.genesisBalanceKeys.push(msg.sender); } - s.genesisBalance[msg.sender] += msg.value; - s.genesisCircSupply += msg.value; + s.genesisBalance[msg.sender] += amount; + s.genesisCircSupply += amount; } /// @notice method to remove funds from the initial balance of a subnet. @@ -55,6 +59,8 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa revert SubnetAlreadyBootstrapped(); } + s.supplySource.transferFunds(payable(msg.sender), amount); + if (s.genesisBalance[msg.sender] < amount) { revert NotEnoughBalance(); } @@ -65,8 +71,6 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa if (s.genesisBalance[msg.sender] == 0) { LibSubnetActor.rmAddressFromBalanceKey(msg.sender); } - - payable(msg.sender).sendValue(amount); } function setValidatorGater(address gater) external notKilled { @@ -116,14 +120,15 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa /// or equal to minimum activation collateral as a result of this operation, /// then subnet will be registered. /// @param publicKey The off-chain 65 byte public key that should be associated with the validator - function join(bytes calldata publicKey) external payable nonReentrant whenNotPaused notKilled { + /// @param amount The amount of collateral provided as stake + function join(bytes calldata publicKey, uint256 amount) external payable nonReentrant whenNotPaused notKilled { // Adding this check to prevent new validators from joining // after the subnet has been bootstrapped, if the subnet mode is not Collateral. // We will increase the functionality in the future to support explicit permissioning. if (s.bootstrapped) { LibSubnetActor.enforceCollateralValidation(); } - if (msg.value == 0) { + if (amount == 0) { revert CollateralIsZero(); } @@ -141,7 +146,9 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa revert NotOwnerOfPublicKey(); } - LibSubnetActor.gateValidatorPowerDelta(msg.sender, 0, msg.value); + LibSubnetActor.gateValidatorPowerDelta(msg.sender, 0, amount); + + s.collateralSource.lock(amount); if (!s.bootstrapped) { // if the subnet has not been bootstrapped, join directly @@ -150,13 +157,13 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa // confirm validators deposit immediately LibStaking.setMetadataWithConfirm(msg.sender, publicKey); - LibStaking.depositWithConfirm(msg.sender, msg.value); + LibStaking.depositWithConfirm(msg.sender, amount); LibSubnetActor.bootstrapSubnetIfNeeded(); } else { // if the subnet has been bootstrapped, join with postponed confirmation. LibStaking.setValidatorMetadata(msg.sender, publicKey); - LibStaking.deposit(msg.sender, msg.value); + LibStaking.deposit(msg.sender, amount); } } @@ -164,11 +171,12 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa /// If the total confirmed collateral of the subnet is greater /// or equal to minimum activation collateral as a result of this operation, /// then subnet will be registered. - function stake() external payable whenNotPaused notKilled { + /// @param amount The amount of collateral provided as stake + function stake(uint256 amount) external payable whenNotPaused notKilled { // disabling validator changes for federated subnets (at least for now // until a more complex mechanism is implemented). LibSubnetActor.enforceCollateralValidation(); - if (msg.value == 0) { + if (amount == 0) { revert CollateralIsZero(); } @@ -177,14 +185,15 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa } uint256 collateral = LibStaking.totalValidatorCollateral(msg.sender); - LibSubnetActor.gateValidatorPowerDelta(msg.sender, collateral, collateral + msg.value); + LibSubnetActor.gateValidatorPowerDelta(msg.sender, collateral, collateral + amount); - if (!s.bootstrapped) { - LibStaking.depositWithConfirm(msg.sender, msg.value); + s.collateralSource.lock(amount); + if (!s.bootstrapped) { + LibStaking.depositWithConfirm(msg.sender, amount); LibSubnetActor.bootstrapSubnetIfNeeded(); } else { - LibStaking.deposit(msg.sender, msg.value); + LibStaking.deposit(msg.sender, amount); } } @@ -213,10 +222,10 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa if (!s.bootstrapped) { LibStaking.withdrawWithConfirm(msg.sender, amount); - return; + s.collateralSource.transferFunds(payable(msg.sender), amount); + } else { + LibStaking.withdraw(msg.sender, amount); } - - LibStaking.withdraw(msg.sender, amount); } /// @notice method that allows a validator to leave the subnet. @@ -249,11 +258,12 @@ contract SubnetActorManagerFacet is SubnetActorModifiers, ReentrancyGuard, Pausa s.genesisBalance[msg.sender] == 0; s.genesisCircSupply -= genesisBalance; LibSubnetActor.rmAddressFromBalanceKey(msg.sender); - payable(msg.sender).sendValue(genesisBalance); + s.collateralSource.transferFunds(payable(msg.sender), genesisBalance); } // interaction must be performed after checks and changes LibStaking.withdrawWithConfirm(msg.sender, amount); + s.collateralSource.transferFunds(payable(msg.sender), amount); return; } LibStaking.withdraw(msg.sender, amount); diff --git a/contracts/contracts/subnet/SubnetActorRewardFacet.sol b/contracts/contracts/subnet/SubnetActorRewardFacet.sol index 1a620006be..1b8b84b7db 100644 --- a/contracts/contracts/subnet/SubnetActorRewardFacet.sol +++ b/contracts/contracts/subnet/SubnetActorRewardFacet.sol @@ -7,10 +7,17 @@ import {ReentrancyGuard} from "../lib/LibReentrancyGuard.sol"; import {SubnetActorModifiers} from "../lib/LibSubnetActorStorage.sol"; import {LibStaking} from "../lib/LibStaking.sol"; import {LibSubnetActor} from "../lib/LibSubnetActor.sol"; +import {AssetHelper} from "../lib/AssetHelper.sol"; +import {Asset} from "../structs/Subnet.sol"; contract SubnetActorRewardFacet is SubnetActorModifiers, ReentrancyGuard, Pausable { + using AssetHelper for Asset; + /// @notice Validator claims their released collateral. function claim() external nonReentrant whenNotPaused { - LibStaking.claimCollateral(msg.sender); + uint256 amount = LibStaking.claimCollateral(msg.sender); + if (amount > 0) { + s.collateralSource.transferFunds(payable(msg.sender), amount); + } } } diff --git a/contracts/test/IntegrationTestBase.sol b/contracts/test/IntegrationTestBase.sol index 6171f81fe8..84eaf54565 100644 --- a/contracts/test/IntegrationTestBase.sol +++ b/contracts/test/IntegrationTestBase.sol @@ -9,7 +9,7 @@ import {ConsensusType} from "../contracts/enums/ConsensusType.sol"; import {IDiamond} from "../contracts/interfaces/IDiamond.sol"; import {IpcEnvelope, BottomUpCheckpoint, IpcMsgKind, ParentFinality, CallMsg} from "../contracts/structs/CrossNet.sol"; import {FvmAddress} from "../contracts/structs/FvmAddress.sol"; -import {SubnetID, SupplyKind, PermissionMode, PermissionMode, Subnet, SupplySource, IPCAddress, Validator} from "../contracts/structs/Subnet.sol"; +import {SubnetID, AssetKind, PermissionMode, PermissionMode, Subnet, Asset, IPCAddress, Validator} from "../contracts/structs/Subnet.sol"; import {SubnetIDHelper} from "../contracts/lib/SubnetIDHelper.sol"; import {FvmAddressHelper} from "../contracts/lib/FvmAddressHelper.sol"; import {CrossMsgHelper} from "../contracts/lib/CrossMsgHelper.sol"; @@ -39,7 +39,7 @@ import {OwnershipFacet} from "../contracts/OwnershipFacet.sol"; import {DiamondLoupeFacet} from "../contracts/diamond/DiamondLoupeFacet.sol"; import {DiamondCutFacet} from "../contracts/diamond/DiamondCutFacet.sol"; -import {SupplySourceHelper} from "../contracts/lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../contracts/lib/AssetHelper.sol"; import {TestUtils} from "./helpers/TestUtils.sol"; import {SelectorLibrary} from "./helpers/SelectorLibrary.sol"; import {GatewayFacetsHelper} from "./helpers/GatewayFacetsHelper.sol"; @@ -61,6 +61,18 @@ struct RootSubnetDefinition { SubnetID id; } +contract SubnetWithNativeTokenMock { + function supplySource() public pure returns (Asset memory t) { + return t; + } + + function collateralSource() public pure returns (Asset memory t) { + return t; + } + + receive() external payable {} +} + contract TestParams { uint64 constant MAX_NONCE = type(uint64).max; address constant BLS_ACCOUNT_ADDREESS = address(0xfF000000000000000000000000000000bEefbEEf); @@ -73,8 +85,6 @@ contract TestParams { bytes constant GENESIS = EMPTY_BYTES; uint256 constant DEFAULT_CROSS_MSG_FEE = 10 gwei; uint256 constant DEFAULT_RELAYER_REWARD = 10 gwei; - address constant CHILD_NETWORK_ADDRESS = address(10); - address constant CHILD_NETWORK_ADDRESS_2 = address(11); uint64 constant EPOCH_ONE = 1 * DEFAULT_CHECKPOINT_PERIOD; uint256 constant INITIAL_VALIDATOR_FUNDS = 1 ether; uint16 constant DEFAULT_ACTIVE_VALIDATORS_LIMIT = 100; @@ -84,6 +94,9 @@ contract TestParams { address constant DEFAULT_IPC_GATEWAY_ADDR = address(1024); address constant TOPDOWN_VALIDATOR_1 = address(12); bytes32 constant DEFAULT_COMMIT_SHA = "c7d8f53f"; + + address CHILD_NETWORK_ADDRESS = address(new SubnetWithNativeTokenMock()); + address CHILD_NETWORK_ADDRESS_2 = address(new SubnetWithNativeTokenMock()); } contract TestRegistry is Test, TestParams { @@ -170,14 +183,38 @@ contract TestSubnetActor is Test, TestParams { address gw, SubnetID memory parentID ) internal pure returns (SubnetActorDiamond.ConstructorParams memory) { - SupplySource memory native = SupplySourceHelper.native(); + Asset memory native = AssetHelper.native(); return defaultSubnetActorParamsWith(gw, parentID, native); } function defaultSubnetActorParamsWith( address gw, SubnetID memory parentID, - SupplySource memory source + Asset memory source + ) internal pure returns (SubnetActorDiamond.ConstructorParams memory) { + SubnetActorDiamond.ConstructorParams memory params = SubnetActorDiamond.ConstructorParams({ + parentId: parentID, + ipcGatewayAddr: gw, + consensus: ConsensusType.Fendermint, + minActivationCollateral: DEFAULT_COLLATERAL_AMOUNT, + minValidators: DEFAULT_MIN_VALIDATORS, + bottomUpCheckPeriod: DEFAULT_CHECKPOINT_PERIOD, + majorityPercentage: DEFAULT_MAJORITY_PERCENTAGE, + activeValidatorsLimit: DEFAULT_ACTIVE_VALIDATORS_LIMIT, + powerScale: DEFAULT_POWER_SCALE, + permissionMode: PermissionMode.Collateral, + supplySource: source, + collateralSource: AssetHelper.native(), + validatorGater: address(0) + }); + return params; + } + + function defaultSubnetActorParamsWith( + address gw, + SubnetID memory parentID, + Asset memory source, + Asset memory collateral ) internal pure returns (SubnetActorDiamond.ConstructorParams memory) { SubnetActorDiamond.ConstructorParams memory params = SubnetActorDiamond.ConstructorParams({ parentId: parentID, @@ -191,6 +228,7 @@ contract TestSubnetActor is Test, TestParams { powerScale: DEFAULT_POWER_SCALE, permissionMode: PermissionMode.Collateral, supplySource: source, + collateralSource: collateral, validatorGater: address(0) }); return params; @@ -203,7 +241,7 @@ contract TestSubnetActor is Test, TestParams { defaultSubnetActorParamsWith( gw, SubnetID({root: ROOTNET_CHAINID, route: new address[](0)}), - SupplySourceHelper.native() + AssetHelper.native() ); } @@ -223,7 +261,8 @@ contract TestSubnetActor is Test, TestParams { activeValidatorsLimit: DEFAULT_ACTIVE_VALIDATORS_LIMIT, powerScale: DEFAULT_POWER_SCALE, permissionMode: PermissionMode.Collateral, - supplySource: SupplySource({kind: SupplyKind.ERC20, tokenAddress: tokenAddress}), + supplySource: Asset({kind: AssetKind.ERC20, tokenAddress: tokenAddress}), + collateralSource: AssetHelper.native(), validatorGater: address(0) }); return params; @@ -232,7 +271,7 @@ contract TestSubnetActor is Test, TestParams { contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, TestGatewayActor { using SubnetIDHelper for SubnetID; - using SupplySourceHelper for SupplySource; + using AssetHelper for Asset; using CrossMsgHelper for IpcEnvelope; using FvmAddressHelper for FvmAddress; using GatewayFacetsHelper for address; @@ -265,7 +304,7 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, addValidator(TOPDOWN_VALIDATOR_1, 100); } - function defaultGatewayParams() internal pure virtual returns (GatewayDiamond.ConstructorParams memory) { + function defaultGatewayParams() internal view virtual returns (GatewayDiamond.ConstructorParams memory) { GatewayDiamond.ConstructorParams memory params = GatewayDiamond.ConstructorParams({ networkName: SubnetID({root: ROOTNET_CHAINID, route: new address[](0)}), bottomUpCheckPeriod: DEFAULT_CHECKPOINT_PERIOD, @@ -565,7 +604,8 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, activeValidatorsLimit: _activeValidatorsLimit, powerScale: 12, permissionMode: _permissionMode, - supplySource: SupplySourceHelper.native(), + supplySource: AssetHelper.native(), + collateralSource: AssetHelper.native(), validatorGater: address(0) }); saDiamond = createSubnetActor(params); @@ -595,7 +635,8 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, activeValidatorsLimit: _activeValidatorsLimit, powerScale: 12, permissionMode: _permissionMode, - supplySource: SupplySourceHelper.native(), + supplySource: AssetHelper.native(), + collateralSource: AssetHelper.native(), validatorGater: _validatorGater }); saDiamond = createSubnetActor(params); @@ -781,10 +822,10 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, } function fund(address funderAddress, uint256 fundAmount) public { - fund(funderAddress, fundAmount, SupplyKind.Native); + fund(funderAddress, fundAmount, AssetKind.Native); } - function fund(address funderAddress, uint256 fundAmount, SupplyKind mode) public { + function fund(address funderAddress, uint256 fundAmount, AssetKind mode) public { // funding subnets is free, we do not need cross msg fee (SubnetID memory subnetId, , uint256 nonceBefore, , uint256 circSupplyBefore) = getSubnet(address(saDiamond)); @@ -792,9 +833,9 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, uint256 expectedNonce = nonceBefore + 1; uint256 expectedCircSupply = circSupplyBefore + fundAmount; - if (mode == SupplyKind.Native) { + if (mode == AssetKind.Native) { gatewayDiamond.manager().fund{value: fundAmount}(subnetId, FvmAddressHelper.from(funderAddress)); - } else if (mode == SupplyKind.ERC20) { + } else if (mode == AssetKind.ERC20) { gatewayDiamond.manager().fundWithToken(subnetId, FvmAddressHelper.from(funderAddress), fundAmount); } @@ -812,7 +853,7 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, function join(address validatorAddress, bytes memory pubkey) public { vm.prank(validatorAddress); vm.deal(validatorAddress, DEFAULT_COLLATERAL_AMOUNT + 1); - saDiamond.manager().join{value: DEFAULT_COLLATERAL_AMOUNT}(pubkey); + saDiamond.manager().join{value: DEFAULT_COLLATERAL_AMOUNT}(pubkey, DEFAULT_COLLATERAL_AMOUNT); } function confirmChange(address validator, uint256 privKey) internal { @@ -899,7 +940,7 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, (, uint256 stakedBefore, , , ) = getSubnet(subnetAddress); - gatewayDiamond.manager().addStake{value: stakeAmount}(); + gatewayDiamond.manager().addStake{value: stakeAmount}(stakeAmount); uint256 balanceAfter = subnetAddress.balance; (, uint256 stakedAfter, , , ) = getSubnet(subnetAddress); @@ -912,7 +953,7 @@ contract IntegrationTestBase is Test, TestParams, TestRegistry, TestSubnetActor, GatewayManagerFacet manager = gw.manager(); GatewayGetterFacet getter = gw.getter(); - manager.register{value: collateral}(0); + manager.register{value: collateral}(0, collateral); (SubnetID memory id, uint256 stake, uint256 topDownNonce, , uint256 circSupply) = getSubnetGW( subnetAddress, diff --git a/contracts/test/IntegrationTestPresets.sol b/contracts/test/IntegrationTestPresets.sol index c9833f6fe2..da155ad6cd 100644 --- a/contracts/test/IntegrationTestPresets.sol +++ b/contracts/test/IntegrationTestPresets.sol @@ -22,7 +22,7 @@ contract L1GatewayActorDiamond is IntegrationTestBase { gatewayDiamond = createGatewayDiamond(gwConstructorParams); } - function defaultGatewayParams() internal pure override returns (GatewayDiamond.ConstructorParams memory) { + function defaultGatewayParams() internal view override returns (GatewayDiamond.ConstructorParams memory) { address[] memory path = new address[](1); path[0] = CHILD_NETWORK_ADDRESS; @@ -48,7 +48,7 @@ contract L2GatewayActorDiamond is IntegrationTestBase { gatewayDiamond = createGatewayDiamond(gwConstructorParams); } - function defaultGatewayParams() internal pure override returns (GatewayDiamond.ConstructorParams memory) { + function defaultGatewayParams() internal view override returns (GatewayDiamond.ConstructorParams memory) { address[] memory path = new address[](2); path[0] = CHILD_NETWORK_ADDRESS; path[1] = CHILD_NETWORK_ADDRESS_2; @@ -77,7 +77,7 @@ contract L3GatewayActorDiamond is IntegrationTestBase { gatewayDiamond = createGatewayDiamond(gwConstructorParams); } - function defaultGatewayParams() internal pure override returns (GatewayDiamond.ConstructorParams memory) { + function defaultGatewayParams() internal view override returns (GatewayDiamond.ConstructorParams memory) { address[] memory path = new address[](3); path[0] = CHILD_NETWORK_ADDRESS; path[1] = CHILD_NETWORK_ADDRESS_2; diff --git a/contracts/test/helpers/SelectorLibrary.sol b/contracts/test/helpers/SelectorLibrary.sol index 4259f877c6..adcdc5e965 100644 --- a/contracts/test/helpers/SelectorLibrary.sol +++ b/contracts/test/helpers/SelectorLibrary.sol @@ -34,7 +34,7 @@ library SelectorLibrary { if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("GatewayManagerFacet"))) { return abi.decode( - hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000075a627dbc0000000000000000000000000000000000000000000000000000000018f44b70000000000000000000000000000000000000000000000000000000000517e1aa0000000000000000000000000000000000000000000000000000000041c0e1b500000000000000000000000000000000000000000000000000000000f207564e000000000000000000000000000000000000000000000000000000006b2c1eef0000000000000000000000000000000000000000000000000000000045f5448500000000000000000000000000000000000000000000000000000000", + hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000007eb4f16b50000000000000000000000000000000000000000000000000000000018f44b70000000000000000000000000000000000000000000000000000000000517e1aa0000000000000000000000000000000000000000000000000000000041c0e1b500000000000000000000000000000000000000000000000000000000d66d6c10000000000000000000000000000000000000000000000000000000006b2c1eef0000000000000000000000000000000000000000000000000000000045f5448500000000000000000000000000000000000000000000000000000000", (bytes4[]) ); } @@ -69,14 +69,14 @@ library SelectorLibrary { if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorGetterFacet"))) { return abi.decode( - hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001f3354c3e10000000000000000000000000000000000000000000000000000000035142c8c0000000000000000000000000000000000000000000000000000000006c46853000000000000000000000000000000000000000000000000000000004b27aa72000000000000000000000000000000000000000000000000000000004b0694e2000000000000000000000000000000000000000000000000000000008ef3f76100000000000000000000000000000000000000000000000000000000e02d971b00000000000000000000000000000000000000000000000000000000903e693000000000000000000000000000000000000000000000000000000000948628a900000000000000000000000000000000000000000000000000000000d92e8f1200000000000000000000000000000000000000000000000000000000c7cda762000000000000000000000000000000000000000000000000000000009754b29e0000000000000000000000000000000000000000000000000000000038a210b30000000000000000000000000000000000000000000000000000000080f76021000000000000000000000000000000000000000000000000000000005dd9147c00000000000000000000000000000000000000000000000000000000d6eb591000000000000000000000000000000000000000000000000000000000332a5ac9000000000000000000000000000000000000000000000000000000001597bf7e0000000000000000000000000000000000000000000000000000000052d182d1000000000000000000000000000000000000000000000000000000001904bb2e00000000000000000000000000000000000000000000000000000000cfca28240000000000000000000000000000000000000000000000000000000040550a1c00000000000000000000000000000000000000000000000000000000d081be03000000000000000000000000000000000000000000000000000000001f3a0e410000000000000000000000000000000000000000000000000000000072d0a0e000000000000000000000000000000000000000000000000000000000599c7bd1000000000000000000000000000000000000000000000000000000009e33bd0200000000000000000000000000000000000000000000000000000000c5ab224100000000000000000000000000000000000000000000000000000000f0cf6c9600000000000000000000000000000000000000000000000000000000ad81e4d60000000000000000000000000000000000000000000000000000000080875df700000000000000000000000000000000000000000000000000000000", + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000203354c3e10000000000000000000000000000000000000000000000000000000035142c8c0000000000000000000000000000000000000000000000000000000006c46853000000000000000000000000000000000000000000000000000000004b27aa72000000000000000000000000000000000000000000000000000000004b0694e200000000000000000000000000000000000000000000000000000000b6797d3c000000000000000000000000000000000000000000000000000000008ef3f76100000000000000000000000000000000000000000000000000000000e02d971b00000000000000000000000000000000000000000000000000000000903e693000000000000000000000000000000000000000000000000000000000948628a900000000000000000000000000000000000000000000000000000000d92e8f1200000000000000000000000000000000000000000000000000000000c7cda762000000000000000000000000000000000000000000000000000000009754b29e0000000000000000000000000000000000000000000000000000000038a210b30000000000000000000000000000000000000000000000000000000080f76021000000000000000000000000000000000000000000000000000000005dd9147c00000000000000000000000000000000000000000000000000000000d6eb591000000000000000000000000000000000000000000000000000000000332a5ac9000000000000000000000000000000000000000000000000000000001597bf7e0000000000000000000000000000000000000000000000000000000052d182d1000000000000000000000000000000000000000000000000000000001904bb2e00000000000000000000000000000000000000000000000000000000cfca28240000000000000000000000000000000000000000000000000000000040550a1c00000000000000000000000000000000000000000000000000000000d081be03000000000000000000000000000000000000000000000000000000001f3a0e410000000000000000000000000000000000000000000000000000000072d0a0e000000000000000000000000000000000000000000000000000000000599c7bd1000000000000000000000000000000000000000000000000000000009e33bd0200000000000000000000000000000000000000000000000000000000c5ab224100000000000000000000000000000000000000000000000000000000f0cf6c9600000000000000000000000000000000000000000000000000000000ad81e4d60000000000000000000000000000000000000000000000000000000080875df700000000000000000000000000000000000000000000000000000000", (bytes4[]) ); } if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorManagerFacet"))) { return abi.decode( - hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a10fd4261000000000000000000000000000000000000000000000000000000006170b1620000000000000000000000000000000000000000000000000000000041c0e1b500000000000000000000000000000000000000000000000000000000d66d9e19000000000000000000000000000000000000000000000000000000000b7fbe600000000000000000000000000000000000000000000000000000000066783c9b00000000000000000000000000000000000000000000000000000000da5d09ee00000000000000000000000000000000000000000000000000000000dcda8973000000000000000000000000000000000000000000000000000000003a4b66f1000000000000000000000000000000000000000000000000000000002e17de7800000000000000000000000000000000000000000000000000000000", + hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a10fd4261000000000000000000000000000000000000000000000000000000003ae247130000000000000000000000000000000000000000000000000000000041c0e1b500000000000000000000000000000000000000000000000000000000d66d9e19000000000000000000000000000000000000000000000000000000004d9013a10000000000000000000000000000000000000000000000000000000066783c9b00000000000000000000000000000000000000000000000000000000da5d09ee00000000000000000000000000000000000000000000000000000000dcda897300000000000000000000000000000000000000000000000000000000a694fc3a000000000000000000000000000000000000000000000000000000002e17de7800000000000000000000000000000000000000000000000000000000", (bytes4[]) ); } @@ -104,7 +104,7 @@ library SelectorLibrary { if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("RegisterSubnetFacet"))) { return abi.decode( - hex"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001ce9513e800000000000000000000000000000000000000000000000000000000", + hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000018471614600000000000000000000000000000000000000000000000000000000", (bytes4[]) ); } diff --git a/contracts/test/helpers/TestUtils.sol b/contracts/test/helpers/TestUtils.sol index a840722cd2..5df49f8861 100644 --- a/contracts/test/helpers/TestUtils.sol +++ b/contracts/test/helpers/TestUtils.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.23; import "forge-std/Test.sol"; import "elliptic-curve-solidity/contracts/EllipticCurve.sol"; -import {IPCAddress} from "../../contracts/structs/Subnet.sol"; +import {IPCAddress, Asset} from "../../contracts/structs/Subnet.sol"; import {CallMsg, IpcMsgKind, IpcEnvelope} from "../../contracts/structs/CrossNet.sol"; import {IIpcHandler} from "../../sdk/interfaces/IIpcHandler.sol"; import {METHOD_SEND, EMPTY_BYTES} from "../../contracts/constants/Constants.sol"; @@ -177,6 +177,16 @@ contract MockIpcContract is IIpcHandler { function handleIpcMessage(IpcEnvelope calldata) external payable returns (bytes memory ret) { return EMPTY_BYTES; } + + function supplySource() public pure returns (Asset memory t) { + return t; + } + + function collateralSource() public pure returns (Asset memory t) { + return t; + } + + receive() external payable {} } contract MockIpcContractFallback is IIpcHandler { diff --git a/contracts/test/integration/GatewayDiamond.t.sol b/contracts/test/integration/GatewayDiamond.t.sol index 928e5549fa..0759b98f08 100644 --- a/contracts/test/integration/GatewayDiamond.t.sol +++ b/contracts/test/integration/GatewayDiamond.t.sol @@ -14,7 +14,7 @@ import {IDiamondCut} from "../../contracts/interfaces/IDiamondCut.sol"; import {QuorumInfo} from "../../contracts/structs/Quorum.sol"; import {IpcEnvelope, BottomUpMsgBatch, BottomUpCheckpoint, ParentFinality} from "../../contracts/structs/CrossNet.sol"; import {FvmAddress} from "../../contracts/structs/FvmAddress.sol"; -import {SubnetID, Subnet, IPCAddress, Validator, StakingChange, StakingChangeRequest, StakingOperation} from "../../contracts/structs/Subnet.sol"; +import {SubnetID, Subnet, IPCAddress, Validator, StakingChange, StakingChangeRequest, Asset, StakingOperation} from "../../contracts/structs/Subnet.sol"; import {SubnetIDHelper} from "../../contracts/lib/SubnetIDHelper.sol"; import {FvmAddressHelper} from "../../contracts/lib/FvmAddressHelper.sol"; import {CrossMsgHelper} from "../../contracts/lib/CrossMsgHelper.sol"; @@ -32,14 +32,14 @@ import {DiamondCutFacet} from "../../contracts/diamond/DiamondCutFacet.sol"; import {LibDiamond} from "../../contracts/lib/LibDiamond.sol"; import {MerkleTreeHelper} from "../helpers/MerkleTreeHelper.sol"; import {TestUtils, MockIpcContract} from "../helpers/TestUtils.sol"; -import {IntegrationTestBase} from "../IntegrationTestBase.sol"; +import {IntegrationTestBase, SubnetWithNativeTokenMock} from "../IntegrationTestBase.sol"; import {SelectorLibrary} from "../helpers/SelectorLibrary.sol"; import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; import {SubnetActorDiamond} from "../../contracts/SubnetActorDiamond.sol"; import {SubnetActorFacetsHelper} from "../helpers/SubnetActorFacetsHelper.sol"; -contract GatewayActorDiamondTest is Test, IntegrationTestBase { +contract GatewayActorDiamondTest is Test, IntegrationTestBase, SubnetWithNativeTokenMock { using SubnetIDHelper for SubnetID; using CrossMsgHelper for IpcEnvelope; using FvmAddressHelper for FvmAddress; @@ -265,7 +265,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { function testGatewayDiamond_Register_Works_SingleSubnet(uint256 subnetCollateral) public { vm.assume(subnetCollateral < type(uint64).max); - address subnetAddress = vm.addr(100); + address subnetAddress = address(new SubnetWithNativeTokenMock()); vm.prank(subnetAddress); vm.deal(subnetAddress, subnetCollateral); @@ -291,7 +291,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { vm.assume(numberOfSubnets > 0); for (uint256 i = 1; i <= numberOfSubnets; i++) { - address subnetAddress = vm.addr(i); + address subnetAddress = address(new SubnetWithNativeTokenMock()); vm.prank(subnetAddress); vm.deal(subnetAddress, DEFAULT_COLLATERAL_AMOUNT); @@ -308,11 +308,11 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { vm.expectRevert(AlreadyRegisteredSubnet.selector); - gatewayDiamond.manager().register{value: DEFAULT_COLLATERAL_AMOUNT}(0); + gatewayDiamond.manager().register{value: DEFAULT_COLLATERAL_AMOUNT}(0, DEFAULT_COLLATERAL_AMOUNT); } function testGatewayDiamond_AddStake_Works_SingleStaking(uint256 stakeAmount, uint256 registerAmount) public { - address subnetAddress = vm.addr(100); + address subnetAddress = address(new SubnetWithNativeTokenMock()); vm.assume(registerAmount < type(uint64).max); vm.assume(stakeAmount > 0 && stakeAmount < type(uint256).max - registerAmount); @@ -330,7 +330,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { } function testGatewayDiamond_AddStake_Works_Reactivate() public { - address subnetAddress = vm.addr(100); + address subnetAddress = address(new SubnetWithNativeTokenMock()); uint256 registerAmount = DEFAULT_COLLATERAL_AMOUNT; uint256 stakeAmount = DEFAULT_COLLATERAL_AMOUNT; @@ -349,7 +349,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { } function testGatewayDiamond_AddStake_Works_NotEnoughFundsToReactivate() public { - address subnetAddress = vm.addr(100); + address subnetAddress = address(new SubnetWithNativeTokenMock()); uint256 registerAmount = DEFAULT_COLLATERAL_AMOUNT; uint256 stakeAmount = DEFAULT_COLLATERAL_AMOUNT - 1; @@ -370,7 +370,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { function testGatewayDiamond_AddStake_Works_MultipleStakings(uint8 numberOfStakes) public { vm.assume(numberOfStakes > 0); - address subnetAddress = vm.addr(100); + address subnetAddress = address(new SubnetWithNativeTokenMock()); uint256 singleStakeAmount = 1 ether; uint256 registerAmount = DEFAULT_COLLATERAL_AMOUNT; uint256 expectedStakedAmount = registerAmount; @@ -396,13 +396,13 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { vm.expectRevert(NotEnoughFunds.selector); - gatewayDiamond.manager().addStake{value: 0}(); + gatewayDiamond.manager().addStake{value: 0}(0); } function testGatewayDiamond_AddStake_Fail_SubnetNotExists() public { vm.expectRevert(NotRegisteredSubnet.selector); - gatewayDiamond.manager().addStake{value: 1}(); + gatewayDiamond.manager().addStake{value: 1}(1); } function testGatewayDiamond_ReleaseStake_Works_FullAmount(uint256 stakeAmount) public { @@ -428,7 +428,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { } function testGatewayDiamond_ReleaseStake_Works_SubnetInactive() public { - address subnetAddress = vm.addr(100); + address subnetAddress = address(new SubnetWithNativeTokenMock()); vm.startPrank(subnetAddress); vm.deal(subnetAddress, DEFAULT_COLLATERAL_AMOUNT); registerSubnet(DEFAULT_COLLATERAL_AMOUNT, subnetAddress); @@ -476,7 +476,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { vm.assume(subnetBalance > DEFAULT_COLLATERAL_AMOUNT); vm.assume(releaseAmount > subnetBalance && releaseAmount < type(uint256).max - subnetBalance); - address subnetAddress = vm.addr(100); + address subnetAddress = address(new SubnetWithNativeTokenMock()); vm.startPrank(subnetAddress); vm.deal(subnetAddress, releaseAmount); @@ -494,7 +494,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { } function testGatewayDiamond_ReleaseStake_Works_TransitionToInactive() public { - address subnetAddress = vm.addr(100); + address subnetAddress = address(new SubnetWithNativeTokenMock()); vm.startPrank(subnetAddress); vm.deal(subnetAddress, DEFAULT_COLLATERAL_AMOUNT); @@ -563,7 +563,7 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { function testGatewayDiamond_SendCrossMessage_Fails_Fuzz(uint256 fee) public { vm.assume(fee < DEFAULT_CROSS_MSG_FEE); - address caller = vm.addr(100); + address caller = CHILD_NETWORK_ADDRESS; vm.deal(caller, DEFAULT_COLLATERAL_AMOUNT + DEFAULT_CROSS_MSG_FEE + 2); vm.prank(caller); registerSubnet(DEFAULT_COLLATERAL_AMOUNT, caller); @@ -899,28 +899,29 @@ contract GatewayActorDiamondTest is Test, IntegrationTestBase { ); } - function testGatewayDiamond_SendCrossMessage_Fails_EoACaller() public { - address caller = vm.addr(100); - vm.startPrank(caller); - vm.deal(caller, DEFAULT_COLLATERAL_AMOUNT + DEFAULT_CROSS_MSG_FEE + 2); - - registerSubnet(DEFAULT_COLLATERAL_AMOUNT, caller); - - SubnetID memory destinationSubnet = SubnetID(0, new address[](0)); - vm.expectRevert(abi.encodeWithSelector(InvalidXnetMessage.selector, InvalidXnetMessageReason.Sender)); - - gatewayDiamond.messenger().sendContractXnetMessage{value: DEFAULT_CROSS_MSG_FEE}( - TestUtils.newXnetCallMsg( - IPCAddress({ - subnetId: SubnetID({root: ROOTNET_CHAINID, route: new address[](0)}), - rawAddress: FvmAddressHelper.from(caller) - }), - IPCAddress({subnetId: destinationSubnet, rawAddress: FvmAddressHelper.from(caller)}), - 1, - 0 - ) - ); - } + // TODO: this is no longer possible because EOA cannot be subnet + // function testGatewayDiamond_SendCrossMessage_Fails_EoACaller() public { + // address caller = vm.addr(100); + // vm.startPrank(caller); + // vm.deal(caller, DEFAULT_COLLATERAL_AMOUNT + DEFAULT_CROSS_MSG_FEE + 2); + + // registerSubnet(DEFAULT_COLLATERAL_AMOUNT, caller); + + // SubnetID memory destinationSubnet = SubnetID(0, new address[](0)); + // vm.expectRevert(abi.encodeWithSelector(InvalidXnetMessage.selector, InvalidXnetMessageReason.Sender)); + + // gatewayDiamond.messenger().sendContractXnetMessage{value: DEFAULT_CROSS_MSG_FEE}( + // TestUtils.newXnetCallMsg( + // IPCAddress({ + // subnetId: SubnetID({root: ROOTNET_CHAINID, route: new address[](0)}), + // rawAddress: FvmAddressHelper.from(caller) + // }), + // IPCAddress({subnetId: destinationSubnet, rawAddress: FvmAddressHelper.from(caller)}), + // 1, + // 0 + // ) + // ); + // } function testGatewayDiamond_SendCrossMessage_Fails_EmptyNetwork() public { // Caller of general-purpose messages must be a contract, not a EoA diff --git a/contracts/test/integration/GatewayDiamondToken.t.sol b/contracts/test/integration/GatewayDiamondToken.t.sol index 8fda55a7f0..74f6223cf3 100644 --- a/contracts/test/integration/GatewayDiamondToken.t.sol +++ b/contracts/test/integration/GatewayDiamondToken.t.sol @@ -7,12 +7,12 @@ import "../../contracts/errors/IPCErrors.sol"; import {EMPTY_BYTES, METHOD_SEND, EMPTY_HASH} from "../../contracts/constants/Constants.sol"; import {IpcEnvelope, BottomUpMsgBatch, BottomUpCheckpoint} from "../../contracts/structs/CrossNet.sol"; import {FvmAddress} from "../../contracts/structs/FvmAddress.sol"; -import {IPCAddress, SubnetID, Subnet, SupplySource, SupplyKind, Validator} from "../../contracts/structs/Subnet.sol"; +import {IPCAddress, SubnetID, Subnet, Asset, AssetKind, Validator} from "../../contracts/structs/Subnet.sol"; import {SubnetIDHelper} from "../../contracts/lib/SubnetIDHelper.sol"; import {FvmAddressHelper} from "../../contracts/lib/FvmAddressHelper.sol"; import {CrossMsgHelper} from "../../contracts/lib/CrossMsgHelper.sol"; import {IIpcHandler} from "../../sdk/interfaces/IIpcHandler.sol"; -import {SupplySourceHelper} from "../../contracts/lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../../contracts/lib/AssetHelper.sol"; import {FilAddress} from "fevmate/contracts/utils/FilAddress.sol"; import {GatewayDiamond} from "../../contracts/GatewayDiamond.sol"; import {LibGateway} from "../../contracts/lib/LibGateway.sol"; @@ -57,7 +57,7 @@ contract GatewayDiamondTokenTest is Test, IntegrationTestBase { (SubnetID memory subnetId, , , , ) = getSubnet(address(saDiamond)); vm.prank(caller); - vm.expectRevert(SupplySourceHelper.UnexpectedSupplySource.selector); + vm.expectRevert("Unexpected asset"); gatewayDiamond.manager().fundWithToken(subnetId, FvmAddressHelper.from(caller), 100); } @@ -68,7 +68,7 @@ contract GatewayDiamondTokenTest is Test, IntegrationTestBase { Subnet memory subnet = createTokenSubnet(address(token)); vm.prank(caller); - vm.expectRevert(SupplySourceHelper.UnexpectedSupplySource.selector); + vm.expectRevert("Unexpected asset"); gatewayDiamond.manager().fund{value: 100}(subnet.id, FvmAddressHelper.from(caller)); } @@ -243,7 +243,7 @@ contract GatewayDiamondTokenTest is Test, IntegrationTestBase { SubnetActorDiamond.ConstructorParams memory saConstructorParams = defaultSubnetActorParamsWith( address(gatewayDiamond) ); - saConstructorParams.supplySource = SupplySource({kind: SupplyKind.ERC20, tokenAddress: tokenAddress}); + saConstructorParams.supplySource = Asset({kind: AssetKind.ERC20, tokenAddress: tokenAddress}); // Override the state variables with the new subnet. saDiamond = createSubnetActor(saConstructorParams); diff --git a/contracts/test/integration/MultiSubnet.t.sol b/contracts/test/integration/MultiSubnet.t.sol index b2c473f480..088f828fb0 100644 --- a/contracts/test/integration/MultiSubnet.t.sol +++ b/contracts/test/integration/MultiSubnet.t.sol @@ -8,7 +8,7 @@ import {IpcEnvelope, BottomUpMsgBatch, BottomUpCheckpoint, ParentFinality, IpcMs import {FvmAddress} from "../../contracts/structs/FvmAddress.sol"; import {SubnetID, Subnet, IPCAddress, Validator} from "../../contracts/structs/Subnet.sol"; import {SubnetIDHelper} from "../../contracts/lib/SubnetIDHelper.sol"; -import {SupplySourceHelper} from "../../contracts/lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../../contracts/lib/AssetHelper.sol"; import {FvmAddressHelper} from "../../contracts/lib/FvmAddressHelper.sol"; import {CrossMsgHelper} from "../../contracts/lib/CrossMsgHelper.sol"; import {GatewayDiamond, FEATURE_MULTILEVEL_CROSSMSG} from "../../contracts/GatewayDiamond.sol"; @@ -448,7 +448,7 @@ contract MultiSubnetTest is Test, IntegrationTestBase { registerSubnetGW(DEFAULT_COLLATERAL_AMOUNT, nilTokenSubnet.subnetActorAddr, rootSubnet.gateway); vm.prank(caller); - vm.expectRevert(SupplySourceHelper.NoBalanceIncrease.selector); + vm.expectRevert("No balance increase"); rootSubnet.gateway.manager().fundWithToken(nilTokenSubnet.id, FvmAddressHelper.from(address(caller)), amount); assertEq(getSubnetCircSupplyGW(nilTokenSubnet.id, rootSubnet.gateway), 0); } @@ -1398,7 +1398,7 @@ contract MultiSubnetTest is Test, IntegrationTestBase { vm.deal(parentValidators[i], 10 gwei); parentPubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(parentKeys[i]); vm.prank(parentValidators[i]); - manager.join{value: 10}(parentPubKeys[i]); + manager.join{value: 10}(parentPubKeys[i], 10); } bytes32 hash = keccak256(abi.encode(checkpoint)); diff --git a/contracts/test/integration/SubnetActorDiamond.t.sol b/contracts/test/integration/SubnetActorDiamond.t.sol index ff2bcdf453..85f57e1356 100644 --- a/contracts/test/integration/SubnetActorDiamond.t.sol +++ b/contracts/test/integration/SubnetActorDiamond.t.sol @@ -12,7 +12,7 @@ import {METHOD_SEND} from "../../contracts/constants/Constants.sol"; import {ConsensusType} from "../../contracts/enums/ConsensusType.sol"; import {BottomUpMsgBatch, IpcEnvelope, BottomUpCheckpoint, MAX_MSGS_PER_BATCH} from "../../contracts/structs/CrossNet.sol"; import {FvmAddress} from "../../contracts/structs/FvmAddress.sol"; -import {SubnetID, PermissionMode, IPCAddress, Subnet, SupplySource, ValidatorInfo} from "../../contracts/structs/Subnet.sol"; +import {SubnetID, PermissionMode, IPCAddress, Subnet, Asset, ValidatorInfo, AssetKind} from "../../contracts/structs/Subnet.sol"; import {IERC165} from "../../contracts/interfaces/IERC165.sol"; import {IGateway} from "../../contracts/interfaces/IGateway.sol"; import {IDiamond} from "../../contracts/interfaces/IDiamond.sol"; @@ -34,12 +34,13 @@ import {FilAddress} from "fevmate/contracts/utils/FilAddress.sol"; import {LibStaking} from "../../contracts/lib/LibStaking.sol"; import {LibDiamond} from "../../contracts/lib/LibDiamond.sol"; import {Pausable} from "../../contracts/lib/LibPausable.sol"; -import {SupplySourceHelper} from "../../contracts/lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../../contracts/lib/AssetHelper.sol"; import {IntegrationTestBase} from "../IntegrationTestBase.sol"; import {SubnetActorFacetsHelper} from "../helpers/SubnetActorFacetsHelper.sol"; import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; +import {ERC20PresetFixedSupply} from "../helpers/ERC20PresetFixedSupply.sol"; import {SubnetValidatorGater} from "../../contracts/examples/SubnetValidatorGater.sol"; contract SubnetActorDiamondTest is Test, IntegrationTestBase { @@ -114,7 +115,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validator2, DEFAULT_MIN_VALIDATOR_STAKE); vm.startPrank(validator1); - saDiamond.manager().join{value: validator1Stake}(publicKey1); + saDiamond.manager().join{value: validator1Stake}(publicKey1, validator1Stake); collateral = validator1Stake; require(gatewayAddress.balance == collateral, "gw balance is incorrect after validator1 joining"); @@ -141,7 +142,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { // subnet bootstrapped and should go through queue // second and third validators join vm.startPrank(validator2); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey2); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey2, DEFAULT_MIN_VALIDATOR_STAKE); // collateral not confirmed yet v = saDiamond.getter().getValidator(validator2); @@ -191,7 +192,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.startPrank(validator1); vm.deal(validator1, stake); - saDiamond.manager().stake{value: stake}(); + saDiamond.manager().stake{value: stake}(stake); v = saDiamond.getter().getValidator(validator1); require(v.totalCollateral == validator1Stake + stake, "unexpected total collateral after stake"); @@ -322,7 +323,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { SubnetActorCheckpointingFacet saDupCheckpointerFaucet = new SubnetActorCheckpointingFacet(); OwnershipFacet saOwnershipFacet = new OwnershipFacet(); - SupplySource memory native = SupplySourceHelper.native(); + Asset memory native = AssetHelper.native(); vm.expectRevert(GatewayCannotBeZero.selector); createSubnetActorDiamondWithFaucets( @@ -338,6 +339,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { powerScale: 12, permissionMode: PermissionMode.Collateral, supplySource: native, + collateralSource: AssetHelper.native(), validatorGater: address(0) }), address(saDupGetterFaucet), @@ -356,7 +358,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.prank(validator); vm.expectRevert(NotOwnerOfPublicKey.selector); - saDiamond.manager().join{value: 10}(new bytes(65)); + saDiamond.manager().join{value: 10}(new bytes(65), 10); } function testSubnetActorDiamond_Join_Fail_InvalidPublicKeyLength() public { @@ -366,7 +368,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.prank(validator); vm.expectRevert(InvalidPublicKeyLength.selector); - saDiamond.manager().join{value: 10}(new bytes(64)); + saDiamond.manager().join{value: 10}(new bytes(64), 10); } function testSubnetActorDiamond_Join_Fail_ZeroColalteral() public { @@ -376,7 +378,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.prank(validator); vm.expectRevert(CollateralIsZero.selector); - saDiamond.manager().join(publicKey); + saDiamond.manager().join(publicKey, 0); } function testSubnetActorDiamond_Bootstrap_Node() public { @@ -384,7 +386,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validator, DEFAULT_MIN_VALIDATOR_STAKE); vm.prank(validator); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); // validator adds empty node vm.prank(validator); @@ -434,13 +436,13 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validator3, DEFAULT_MIN_VALIDATOR_STAKE); vm.prank(validator1); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey1); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey1, DEFAULT_MIN_VALIDATOR_STAKE); vm.prank(validator2); - saDiamond.manager().join{value: 3 * DEFAULT_MIN_VALIDATOR_STAKE}(publicKey2); + saDiamond.manager().join{value: 3 * DEFAULT_MIN_VALIDATOR_STAKE}(publicKey2, 3 * DEFAULT_MIN_VALIDATOR_STAKE); vm.prank(validator3); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey3); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey3, DEFAULT_MIN_VALIDATOR_STAKE); confirmChange(validator1, privKey1); @@ -480,14 +482,14 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.prank(validator); vm.expectRevert(CollateralIsZero.selector); - saDiamond.manager().stake(); + saDiamond.manager().stake(0); vm.prank(validator); vm.expectRevert((abi.encodeWithSelector(MethodNotAllowed.selector, ERR_VALIDATOR_NOT_JOINED))); - saDiamond.manager().stake{value: 10}(); + saDiamond.manager().stake{value: 10}(10); vm.prank(validator); - saDiamond.manager().join{value: 3}(publicKey); + saDiamond.manager().join{value: 3}(publicKey, 3); ValidatorInfo memory info = saDiamond.getter().getValidator(validator); require(info.totalCollateral == 3); @@ -518,7 +520,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.deal(validators[i], 10 gwei); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } saDiamond.checkpointer().validateActiveQuorumSignatures(validators, hash, signatures); @@ -537,7 +539,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.deal(validators[i], 10 gwei); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } // this should trigger `WeightsSumLessThanThreshold` error since the signature weight will be just 100. @@ -572,7 +574,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.deal(validators[i], 10 gwei); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } vm.expectRevert( @@ -592,7 +594,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.deal(validators[i], 10 gwei); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } require(signatures.length == 0, "signatures are not empty"); @@ -613,7 +615,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.deal(validators[i], 10 gwei); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } require(signatures.length == 1, "signatures are not empty"); @@ -640,7 +642,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.deal(validators[i], 10 gwei); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } // swap validators to trigger `InvalidSignatory` error; @@ -664,7 +666,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validators[i], 10 gwei); pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } SubnetID memory localSubnetID = saDiamond.getter().getParent().createSubnetId(address(saDiamond)); @@ -700,7 +702,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(address(saDiamond), 100 ether); vm.prank(address(saDiamond)); gatewayDiamond.manager().register{value: DEFAULT_MIN_VALIDATOR_STAKE + 3 * DEFAULT_CROSS_MSG_FEE}( - 3 * DEFAULT_CROSS_MSG_FEE + 3 * DEFAULT_CROSS_MSG_FEE, + DEFAULT_MIN_VALIDATOR_STAKE ); bytes32 hash = keccak256(abi.encode(checkpoint)); @@ -769,7 +772,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validators[i], 10 gwei); pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } SubnetID memory localSubnetID = saDiamond.getter().getParent().createSubnetId(address(saDiamond)); @@ -807,7 +810,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(address(saDiamond), 100 ether); vm.prank(address(saDiamond)); gatewayDiamond.manager().register{value: DEFAULT_MIN_VALIDATOR_STAKE + 3 * DEFAULT_CROSS_MSG_FEE}( - 3 * DEFAULT_CROSS_MSG_FEE + 3 * DEFAULT_CROSS_MSG_FEE, + DEFAULT_MIN_VALIDATOR_STAKE ); bytes32 hash = keccak256(abi.encode(checkpoint)); @@ -850,13 +854,14 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validators[i], 10 gwei); pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } vm.deal(address(saDiamond), 100 ether); vm.prank(address(saDiamond)); gatewayDiamond.manager().register{value: DEFAULT_MIN_VALIDATOR_STAKE + 3 * DEFAULT_CROSS_MSG_FEE}( - 3 * DEFAULT_CROSS_MSG_FEE + 3 * DEFAULT_CROSS_MSG_FEE, + DEFAULT_MIN_VALIDATOR_STAKE ); SubnetID memory localSubnetID = saDiamond.getter().getParent().createSubnetId(address(saDiamond)); @@ -1007,7 +1012,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validators[i], 10 gwei); pubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(keys[i]); vm.prank(validators[i]); - saDiamond.manager().join{value: 10}(pubKeys[i]); + saDiamond.manager().join{value: 10}(pubKeys[i], 10); } SubnetID memory localSubnetID = saDiamond.getter().getParent().createSubnetId(address(saDiamond)); @@ -1036,7 +1041,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(address(saDiamond), 100 ether); vm.prank(address(saDiamond)); gatewayDiamond.manager().register{value: DEFAULT_MIN_VALIDATOR_STAKE + 6 * DEFAULT_CROSS_MSG_FEE}( - 6 * DEFAULT_CROSS_MSG_FEE + 6 * DEFAULT_CROSS_MSG_FEE, + DEFAULT_MIN_VALIDATOR_STAKE ); bytes32 hash = keccak256(abi.encode(checkpoint)); @@ -1171,7 +1177,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validator, DEFAULT_MIN_VALIDATOR_STAKE); vm.prank(validator); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); require( saDiamond.getter().getValidator(validator).totalCollateral == DEFAULT_MIN_VALIDATOR_STAKE, "initial collateral correct" @@ -1210,7 +1216,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { // pre-fund and pre-release from same address vm.startPrank(preReleaser); vm.deal(preReleaser, 2 * fundAmount); - saDiamond.manager().preFund{value: 2 * fundAmount}(); + saDiamond.manager().preFund{value: 2 * fundAmount}(2 * fundAmount); require(saDiamond.getter().genesisCircSupply() == 2 * fundAmount, "genesis circ supply not correct"); saDiamond.manager().preRelease(fundAmount); require(saDiamond.getter().genesisCircSupply() == fundAmount, "genesis circ supply not correct"); @@ -1229,19 +1235,19 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { // pre-fund from validator and from pre-funder vm.startPrank(validator1); vm.deal(validator1, fundAmount); - saDiamond.manager().preFund{value: fundAmount}(); + saDiamond.manager().preFund{value: fundAmount}(fundAmount); vm.stopPrank(); vm.startPrank(preFunder); vm.deal(preFunder, fundAmount); - saDiamond.manager().preFund{value: fundAmount}(); + saDiamond.manager().preFund{value: fundAmount}(fundAmount); vm.stopPrank(); // initial validator joins vm.deal(validator1, DEFAULT_MIN_VALIDATOR_STAKE); vm.startPrank(validator1); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey1); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey1, DEFAULT_MIN_VALIDATOR_STAKE); vm.stopPrank(); collateral = DEFAULT_MIN_VALIDATOR_STAKE; @@ -1273,7 +1279,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.startPrank(preFunder); vm.expectRevert(SubnetAlreadyBootstrapped.selector); vm.deal(preFunder, fundAmount); - saDiamond.manager().preFund{value: fundAmount}(); + saDiamond.manager().preFund{value: fundAmount}(fundAmount); vm.stopPrank(); } @@ -1287,13 +1293,13 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { // pre-fund from validator vm.startPrank(validator1); vm.deal(validator1, fundAmount); - saDiamond.manager().preFund{value: fundAmount}(); + saDiamond.manager().preFund{value: fundAmount}(fundAmount); vm.stopPrank(); // initial validator joins but doesn't bootstrap the subnet vm.deal(validator1, collateral); vm.startPrank(validator1); - saDiamond.manager().join{value: collateral}(publicKey1); + saDiamond.manager().join{value: collateral}(publicKey1, collateral); require( address(saDiamond).balance == collateral + fundAmount, "subnet balance is incorrect after validator1 joining" @@ -1314,7 +1320,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validator1, DEFAULT_MIN_VALIDATOR_STAKE); vm.startPrank(validator1); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey1); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey1, DEFAULT_MIN_VALIDATOR_STAKE); vm.stopPrank(); // pre-release not allowed with bootstrapped subnet @@ -1336,11 +1342,14 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { } vm.prank(validators[0]); - saDiamond.manager().join{value: 100 * DEFAULT_MIN_VALIDATOR_STAKE}(publicKeys[0]); + saDiamond.manager().join{value: 100 * DEFAULT_MIN_VALIDATOR_STAKE}( + publicKeys[0], + 100 * DEFAULT_MIN_VALIDATOR_STAKE + ); for (uint i = 1; i < n; i++) { vm.prank(validators[i]); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKeys[i]); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKeys[i], DEFAULT_MIN_VALIDATOR_STAKE); } confirmChange(validators[0], privKeys[0]); @@ -1363,11 +1372,14 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { } vm.prank(validators[0]); - saDiamond.manager().join{value: 100 * DEFAULT_MIN_VALIDATOR_STAKE}(publicKeys[0]); + saDiamond.manager().join{value: 100 * DEFAULT_MIN_VALIDATOR_STAKE}( + publicKeys[0], + 100 * DEFAULT_MIN_VALIDATOR_STAKE + ); for (uint i = 1; i < n; i++) { vm.prank(validators[i]); - saDiamond.manager().join{value: 1}(publicKeys[i]); + saDiamond.manager().join{value: 1}(publicKeys[i], 1); } confirmChange(validators[0], privKeys[0]); @@ -1385,7 +1397,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { for (uint i = 0; i < n; i++) { vm.deal(validators[i], 1); vm.prank(validators[i]); - saDiamond.manager().join{value: 1}(publicKeys[i]); + saDiamond.manager().join{value: 1}(publicKeys[i], 1); } require(!saDiamond.getter().bootstrapped()); @@ -1427,12 +1439,12 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { (address validator1, bytes memory publicKey1) = TestUtils.deriveValidatorAddress(100); vm.deal(validator1, DEFAULT_MIN_VALIDATOR_STAKE * 2); vm.prank(validator1); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey1); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey1, DEFAULT_MIN_VALIDATOR_STAKE / 2); (address validator2, bytes memory publicKey2) = TestUtils.deriveValidatorAddress(101); vm.deal(validator2, DEFAULT_MIN_VALIDATOR_STAKE * 2); vm.prank(validator2); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey2); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey2, DEFAULT_MIN_VALIDATOR_STAKE / 2); require(saDiamond.getter().isActiveValidator(validator1), "not active validator 1"); require(saDiamond.getter().isActiveValidator(validator2), "not active validator 2"); @@ -1441,7 +1453,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.expectRevert(abi.encodeWithSelector(MethodNotAllowed.selector, ERR_PERMISSIONED_AND_BOOTSTRAPPED)); vm.prank(validator1); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey1); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey1, DEFAULT_MIN_VALIDATOR_STAKE); vm.expectRevert(abi.encodeWithSelector(MethodNotAllowed.selector, ERR_PERMISSIONED_AND_BOOTSTRAPPED)); (address[] memory validators, , bytes[] memory publicKeys) = TestUtils.newValidators(3); @@ -1458,27 +1470,27 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.expectRevert(abi.encodeWithSelector(MethodNotAllowed.selector, ERR_VALIDATOR_NOT_JOINED)); vm.prank(validator1); - saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(); + saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(DEFAULT_MIN_VALIDATOR_STAKE / 2); vm.prank(validator1); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey1); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey1, DEFAULT_MIN_VALIDATOR_STAKE / 2); require(saDiamond.getter().isActiveValidator(validator1), "active validator 1"); require(!saDiamond.getter().bootstrapped(), "subnet bootstrapped"); vm.expectRevert(abi.encodeWithSelector(MethodNotAllowed.selector, ERR_VALIDATOR_JOINED)); vm.prank(validator1); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey1); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey1, DEFAULT_MIN_VALIDATOR_STAKE / 2); vm.prank(validator1); - saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(); + saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(DEFAULT_MIN_VALIDATOR_STAKE / 2); require(saDiamond.getter().isActiveValidator(validator1), "active validator 1"); (address validator2, bytes memory publicKey2) = TestUtils.deriveValidatorAddress(101); vm.deal(validator2, DEFAULT_MIN_VALIDATOR_STAKE * 2); vm.prank(validator2); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey2); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE / 2}(publicKey2, DEFAULT_MIN_VALIDATOR_STAKE / 2); require(saDiamond.getter().isActiveValidator(validator1), "not active validator 1"); require(saDiamond.getter().bootstrapped(), "subnet not bootstrapped"); @@ -1607,7 +1619,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validators[0], DEFAULT_MIN_VALIDATOR_STAKE * 2); vm.startPrank(validators[0]); vm.expectRevert(abi.encodeWithSelector(MethodNotAllowed.selector, ERR_PERMISSIONED_AND_BOOTSTRAPPED)); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKeys[0]); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKeys[0], DEFAULT_MIN_VALIDATOR_STAKE); } function testSubnetActorDiamond_FederatedValidation_works() public { @@ -1737,11 +1749,11 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.prank(validators[0]); vm.expectRevert(Pausable.EnforcedPause.selector); - saDiamond.manager().join{value: 10}(publicKeys[0]); + saDiamond.manager().join{value: 10}(publicKeys[0], 10); vm.prank(validators[0]); vm.expectRevert(Pausable.EnforcedPause.selector); - saDiamond.manager().stake{value: 10}(); + saDiamond.manager().stake{value: 10}(10); vm.prank(validators[0]); vm.expectRevert(Pausable.EnforcedPause.selector); @@ -1789,6 +1801,515 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { require(!saDiamond.pauser().paused(), "paused"); } + // ---------------------------- + // Tests for collateral token + // ---------------------------- + function testSubnetActorDiamond_CollateralERC20_SupplyERC20_RegisteredInGateway() public { + (address validator, uint256 privKey, bytes memory publicKey) = TestUtils.newValidator(100); + (address validator2, , ) = TestUtils.newValidator(101); + + // a bit of gas for execution, should not be needed + vm.deal(validator, DEFAULT_MIN_VALIDATOR_STAKE - 100); + vm.deal(validator2, DEFAULT_MIN_VALIDATOR_STAKE - 100); + + ERC20PresetFixedSupply sourceToken = new ERC20PresetFixedSupply("t", "t", 100000000000, validator2); + ERC20PresetFixedSupply collateralToken = new ERC20PresetFixedSupply( + "t", + "t", + DEFAULT_MIN_VALIDATOR_STAKE * 10, + validator + ); + + Asset memory source = Asset({kind: AssetKind.ERC20, tokenAddress: address(sourceToken)}); + Asset memory collateral = Asset({kind: AssetKind.ERC20, tokenAddress: address(collateralToken)}); + + gatewayAddress = address(gatewayDiamond); + SubnetActorDiamond.ConstructorParams memory params = defaultSubnetActorParamsWith( + gatewayAddress, + SubnetID(ROOTNET_CHAINID, new address[](0)), + source, + collateral + ); + + saDiamond = createSubnetActor(params); + + vm.prank(validator2); + sourceToken.approve(address(saDiamond.manager()), 100); + vm.prank(validator2); + saDiamond.manager().preFund(100); + + vm.prank(validator); + collateralToken.approve(address(saDiamond.manager()), DEFAULT_MIN_VALIDATOR_STAKE * 2); + + vm.prank(validator); + saDiamond.manager().join(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); + require(collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9); + require(collateralToken.balanceOf(address(saDiamond)) == 0); + require(collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE); + require(sourceToken.balanceOf(gatewayAddress) == 100); + + vm.prank(validator); + saDiamond.manager().stake(DEFAULT_MIN_VALIDATOR_STAKE); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post stake balance wrong" + ); + require( + collateralToken.balanceOf(address(saDiamond)) == DEFAULT_MIN_VALIDATOR_STAKE, + "saDiamond post stake balance wrong" + ); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE, + "gateway post stake balance wrong" + ); + confirmChange(validator, privKey); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post stake confirmed balance wrong" + ); + require(collateralToken.balanceOf(address(saDiamond)) == 0, "saDiamond post stake confirmed balance wrong"); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE * 2, + "gateway post stake confirmed balance wrong" + ); + + vm.prank(validator); + saDiamond.manager().unstake(DEFAULT_MIN_VALIDATOR_STAKE); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post unstake balance wrong" + ); + require(collateralToken.balanceOf(address(saDiamond)) == 0, "saDiamond post unstake balance wrong"); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE * 2, + "gateway post unstake balance wrong" + ); + confirmChange(validator, privKey); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post unstake balance wrong" + ); + require( + collateralToken.balanceOf(address(saDiamond)) == DEFAULT_MIN_VALIDATOR_STAKE, + "saDiamond post unstake balance wrong" + ); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE, + "gateway post unstake balance wrong" + ); + + vm.prank(validator); + saDiamond.rewarder().claim(); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9, + "validator post claim balance wrong" + ); + require(collateralToken.balanceOf(address(saDiamond)) == 0, "saDiamond post claim balance wrong"); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE, + "gateway post claim balance wrong" + ); + + vm.prank(validator); + saDiamond.manager().leave(); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9, + "validator post leave balance wrong" + ); + require(collateralToken.balanceOf(address(saDiamond)) == 0, "saDiamond post leave balance wrong"); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE, + "gateway post leave balance wrong" + ); + confirmChange(validator, privKey); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9, + "validator confirmed leave balance wrong" + ); + require( + collateralToken.balanceOf(address(saDiamond)) == DEFAULT_MIN_VALIDATOR_STAKE, + "saDiamond confirmed leave balance wrong" + ); + require(collateralToken.balanceOf(gatewayAddress) == 0, "gateway confirmed leave balance wrong"); + + vm.prank(validator); + saDiamond.rewarder().claim(); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 10, + "validator post leave claim balance wrong" + ); + require(collateralToken.balanceOf(address(saDiamond)) == 0, "saDiamond post claim balance wrong"); + require(collateralToken.balanceOf(gatewayAddress) == 0, "gateway post leave claim balance wrong"); + } + + function testSubnetActorDiamond_CollateralERC20_SupplyERC20_SameToken_RegisteredInGateway() public { + (address validator, uint256 privKey, bytes memory publicKey) = TestUtils.newValidator(100); + (address validator2, , ) = TestUtils.newValidator(101); + + // a bit of gas for execution, should not be needed + vm.deal(validator, DEFAULT_MIN_VALIDATOR_STAKE - 100); + vm.deal(validator2, DEFAULT_MIN_VALIDATOR_STAKE - 100); + + ERC20PresetFixedSupply token = new ERC20PresetFixedSupply( + "t", + "t", + DEFAULT_MIN_VALIDATOR_STAKE * 20, + validator + ); + + Asset memory gt = Asset({kind: AssetKind.ERC20, tokenAddress: address(token)}); + + gatewayAddress = address(gatewayDiamond); + SubnetActorDiamond.ConstructorParams memory params = defaultSubnetActorParamsWith( + gatewayAddress, + SubnetID(ROOTNET_CHAINID, new address[](0)), + gt, + gt + ); + + saDiamond = createSubnetActor(params); + + vm.prank(validator); + token.transfer(validator2, DEFAULT_MIN_VALIDATOR_STAKE * 10); + + vm.prank(validator2); + token.approve(address(saDiamond.manager()), 100); + vm.prank(validator2); + saDiamond.manager().preFund(100); + + vm.prank(validator); + token.approve(address(saDiamond.manager()), DEFAULT_MIN_VALIDATOR_STAKE * 2); + + vm.prank(validator); + saDiamond.manager().join(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); + require(token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9); + require(token.balanceOf(address(saDiamond)) == 0); + require(token.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE + 100); + + vm.prank(validator); + saDiamond.manager().stake(DEFAULT_MIN_VALIDATOR_STAKE); + require(token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post stake balance wrong"); + require( + token.balanceOf(address(saDiamond)) == DEFAULT_MIN_VALIDATOR_STAKE, + "saDiamond post stake balance wrong" + ); + require( + token.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE + 100, + "gateway post stake balance wrong" + ); + confirmChange(validator, privKey); + require( + token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post stake confirmed balance wrong" + ); + require(token.balanceOf(address(saDiamond)) == 0, "saDiamond post stake confirmed balance wrong"); + require( + token.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE * 2 + 100, + "gateway post stake confirmed balance wrong" + ); + + vm.prank(validator); + saDiamond.manager().unstake(DEFAULT_MIN_VALIDATOR_STAKE); + require(token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post unstake balance wrong"); + require(token.balanceOf(address(saDiamond)) == 0, "saDiamond post unstake balance wrong"); + require( + token.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE * 2 + 100, + "gateway post unstake balance wrong" + ); + confirmChange(validator, privKey); + require(token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post unstake balance wrong"); + require( + token.balanceOf(address(saDiamond)) == DEFAULT_MIN_VALIDATOR_STAKE, + "saDiamond post unstake balance wrong" + ); + require( + token.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE + 100, + "gateway post unstake balance wrong" + ); + + vm.prank(validator); + saDiamond.rewarder().claim(); + require(token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9, "validator post claim balance wrong"); + require(token.balanceOf(address(saDiamond)) == 0, "saDiamond post claim balance wrong"); + require( + token.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE + 100, + "gateway post claim balance wrong" + ); + + vm.prank(validator); + saDiamond.manager().leave(); + require(token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9, "validator post leave balance wrong"); + require(token.balanceOf(address(saDiamond)) == 0, "saDiamond post leave balance wrong"); + require( + token.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE + 100, + "gateway post leave balance wrong" + ); + confirmChange(validator, privKey); + require( + token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9, + "validator confirmed leave balance wrong" + ); + require( + token.balanceOf(address(saDiamond)) == DEFAULT_MIN_VALIDATOR_STAKE, + "saDiamond confirmed leave balance wrong" + ); + require(token.balanceOf(gatewayAddress) == 100, "gateway confirmed leave balance wrong"); + + vm.prank(validator); + saDiamond.rewarder().claim(); + require( + token.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 10, + "validator post leave claim balance wrong" + ); + require(token.balanceOf(address(saDiamond)) == 0, "saDiamond post claim balance wrong"); + require(token.balanceOf(gatewayAddress) == 100, "gateway post leave claim balance wrong"); + } + + function testSubnetActorDiamond_CollateralERC20_SupplyNative_RegisteredInGateway() public { + (address validator, uint256 privKey, bytes memory publicKey) = TestUtils.newValidator(100); + (address validator2, , ) = TestUtils.newValidator(101); + + // a bit of gas for execution, should not be needed + vm.deal(validator, DEFAULT_MIN_VALIDATOR_STAKE - 100); + vm.deal(validator2, DEFAULT_MIN_VALIDATOR_STAKE - 100); + + ERC20PresetFixedSupply collateralToken = new ERC20PresetFixedSupply( + "t", + "t", + DEFAULT_MIN_VALIDATOR_STAKE * 10, + validator + ); + + Asset memory source = AssetHelper.native(); + Asset memory collateral = Asset({kind: AssetKind.ERC20, tokenAddress: address(collateralToken)}); + + gatewayAddress = address(gatewayDiamond); + SubnetActorDiamond.ConstructorParams memory params = defaultSubnetActorParamsWith( + gatewayAddress, + SubnetID(ROOTNET_CHAINID, new address[](0)), + source, + collateral + ); + + saDiamond = createSubnetActor(params); + + vm.prank(validator2); + saDiamond.manager().preFund{value: 100}(100); + + vm.prank(validator); + collateralToken.approve(address(saDiamond.manager()), DEFAULT_MIN_VALIDATOR_STAKE * 2); + + vm.prank(validator); + saDiamond.manager().join(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); + require(collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9); + require(collateralToken.balanceOf(address(saDiamond)) == 0); + require(collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE); + require(address(gatewayAddress).balance == 100); + + vm.prank(validator); + saDiamond.manager().stake(DEFAULT_MIN_VALIDATOR_STAKE); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post stake balance wrong" + ); + require( + collateralToken.balanceOf(address(saDiamond)) == DEFAULT_MIN_VALIDATOR_STAKE, + "saDiamond post stake balance wrong" + ); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE, + "gateway post stake balance wrong" + ); + confirmChange(validator, privKey); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post stake confirmed balance wrong" + ); + require(collateralToken.balanceOf(address(saDiamond)) == 0, "saDiamond post stake confirmed balance wrong"); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE * 2, + "gateway post stake confirmed balance wrong" + ); + + vm.prank(validator); + saDiamond.manager().unstake(DEFAULT_MIN_VALIDATOR_STAKE); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post unstake balance wrong" + ); + require(collateralToken.balanceOf(address(saDiamond)) == 0, "saDiamond post unstake balance wrong"); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE * 2, + "gateway post unstake balance wrong" + ); + confirmChange(validator, privKey); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post unstake balance wrong" + ); + require( + collateralToken.balanceOf(address(saDiamond)) == DEFAULT_MIN_VALIDATOR_STAKE, + "saDiamond post unstake balance wrong" + ); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE, + "gateway post unstake balance wrong" + ); + + vm.prank(validator); + saDiamond.rewarder().claim(); + require( + collateralToken.balanceOf(validator) == DEFAULT_MIN_VALIDATOR_STAKE * 9, + "validator post claim balance wrong" + ); + require(collateralToken.balanceOf(address(saDiamond)) == 0, "saDiamond post claim balance wrong"); + require( + collateralToken.balanceOf(gatewayAddress) == DEFAULT_MIN_VALIDATOR_STAKE, + "gateway post claim balance wrong" + ); + } + + function testSubnetActorDiamond_CollateralNative_SupplyNative_RegisteredInGateway() public { + (address validator, uint256 privKey, bytes memory publicKey) = TestUtils.newValidator(100); + (address validator2, , ) = TestUtils.newValidator(101); + + // a bit of gas for execution, should not be needed + vm.deal(validator, DEFAULT_MIN_VALIDATOR_STAKE * 10); + vm.deal(validator2, DEFAULT_MIN_VALIDATOR_STAKE - 100); + + gatewayAddress = address(gatewayDiamond); + SubnetActorDiamond.ConstructorParams memory params = defaultSubnetActorParamsWith( + gatewayAddress, + SubnetID(ROOTNET_CHAINID, new address[](0)), + AssetHelper.native(), + AssetHelper.native() + ); + + saDiamond = createSubnetActor(params); + + vm.prank(validator2); + saDiamond.manager().preFund{value: 100}(100); + + vm.prank(validator); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 9, "validator post join balance wrong"); + require(address(saDiamond).balance == 0, "saDiamond post join balance wrong"); + require( + address(gatewayAddress).balance == 100 + DEFAULT_MIN_VALIDATOR_STAKE, + "gateway post join balance wrong" + ); + + vm.prank(validator); + saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE}(DEFAULT_MIN_VALIDATOR_STAKE); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post stake balance wrong"); + require(address(saDiamond).balance == DEFAULT_MIN_VALIDATOR_STAKE, "saDiamond post stake balance wrong"); + require( + address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE + 100, + "gateway post stake balance wrong" + ); + confirmChange(validator, privKey); + require( + address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post stake confirmed balance wrong" + ); + require( + address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE * 2 + 100, + "gateway post stake confirmed balance wrong" + ); + + vm.prank(validator); + saDiamond.manager().unstake(DEFAULT_MIN_VALIDATOR_STAKE); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post unstake balance wrong"); + require( + address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE * 2 + 100, + "gateway post unstake balance wrong" + ); + confirmChange(validator, privKey); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post unstake balance wrong"); + require( + address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE + 100, + "gateway post unstake balance wrong" + ); + + vm.prank(validator); + saDiamond.rewarder().claim(); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 9, "validator post claim balance wrong"); + require( + address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE + 100, + "gateway post claim balance wrong" + ); + } + + function testSubnetActorDiamond_CollateralNative_SupplyERC20_RegisteredInGateway() public { + (address validator, uint256 privKey, bytes memory publicKey) = TestUtils.newValidator(100); + (address validator2, , ) = TestUtils.newValidator(101); + + // a bit of gas for execution, should not be needed + vm.deal(validator, DEFAULT_MIN_VALIDATOR_STAKE * 10); + vm.deal(validator2, DEFAULT_MIN_VALIDATOR_STAKE - 100); + + ERC20PresetFixedSupply sourceToken = new ERC20PresetFixedSupply( + "t", + "t", + DEFAULT_MIN_VALIDATOR_STAKE * 10, + validator2 + ); + Asset memory source = Asset({kind: AssetKind.ERC20, tokenAddress: address(sourceToken)}); + + gatewayAddress = address(gatewayDiamond); + SubnetActorDiamond.ConstructorParams memory params = defaultSubnetActorParamsWith( + gatewayAddress, + SubnetID(ROOTNET_CHAINID, new address[](0)), + source, + AssetHelper.native() + ); + + saDiamond = createSubnetActor(params); + + vm.prank(validator2); + sourceToken.approve(address(saDiamond.manager()), 100); + vm.prank(validator2); + saDiamond.manager().preFund(100); + + vm.prank(validator); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 9, "validator post join balance wrong"); + require(address(saDiamond).balance == 0, "saDiamond post join balance wrong"); + require(address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE, "gateway post join balance wrong"); + require(sourceToken.balanceOf(gatewayAddress) == 100, "saDiamond post join balance wrong"); + + vm.prank(validator); + saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE}(DEFAULT_MIN_VALIDATOR_STAKE); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post stake balance wrong"); + require(address(saDiamond).balance == DEFAULT_MIN_VALIDATOR_STAKE, "saDiamond post stake balance wrong"); + require(address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE, "gateway post stake balance wrong"); + confirmChange(validator, privKey); + require( + address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 8, + "validator post stake confirmed balance wrong" + ); + require( + address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE * 2, + "gateway post stake confirmed balance wrong" + ); + + vm.prank(validator); + saDiamond.manager().unstake(DEFAULT_MIN_VALIDATOR_STAKE); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post unstake balance wrong"); + require( + address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE * 2, + "gateway post unstake balance wrong" + ); + confirmChange(validator, privKey); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 8, "validator post unstake balance wrong"); + require(address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE, "gateway post unstake balance wrong"); + + vm.prank(validator); + saDiamond.rewarder().claim(); + require(address(validator).balance == DEFAULT_MIN_VALIDATOR_STAKE * 9, "validator post claim balance wrong"); + require(address(gatewayAddress).balance == DEFAULT_MIN_VALIDATOR_STAKE, "gateway post claim balance wrong"); + } + // ----------------------------------------------------------------------------------------------------------------- // Tests for validator gater // ----------------------------------------------------------------------------------------------------------------- @@ -1824,7 +2345,7 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { vm.deal(validator, DEFAULT_MIN_VALIDATOR_STAKE * 3); vm.prank(validator); vm.expectRevert(ValidatorPowerChangeDenied.selector); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); // now approve the join vm.prank(owner); @@ -1832,16 +2353,16 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase { // should be able to join vm.prank(validator); - saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey); + saDiamond.manager().join{value: DEFAULT_MIN_VALIDATOR_STAKE}(publicKey, DEFAULT_MIN_VALIDATOR_STAKE); // add stake not allowed exceed allowed range vm.prank(validator); vm.expectRevert(ValidatorPowerChangeDenied.selector); - saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE + 1}(); + saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE + 1}(DEFAULT_MIN_VALIDATOR_STAKE + 1); // add stake should be ok vm.prank(validator); - saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE}(); + saDiamond.manager().stake{value: DEFAULT_MIN_VALIDATOR_STAKE}(DEFAULT_MIN_VALIDATOR_STAKE); // unstake not allowed as below allowed range vm.prank(validator); diff --git a/contracts/test/integration/SubnetRegistry.t.sol b/contracts/test/integration/SubnetRegistry.t.sol index a4b9518b17..95c7d8b875 100644 --- a/contracts/test/integration/SubnetRegistry.t.sol +++ b/contracts/test/integration/SubnetRegistry.t.sol @@ -26,7 +26,7 @@ import {SubnetGetterFacet} from "../../contracts/subnetregistry/SubnetGetterFace import {DiamondLoupeFacet} from "../../contracts/diamond/DiamondLoupeFacet.sol"; import {DiamondCutFacet} from "../../contracts/diamond/DiamondCutFacet.sol"; import {OwnershipFacet} from "../../contracts/OwnershipFacet.sol"; -import {SupplySourceHelper} from "../../contracts/lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../../contracts/lib/AssetHelper.sol"; import {RegistryFacetsHelper} from "../helpers/RegistryFacetsHelper.sol"; import {DiamondFacetsHelper} from "../helpers/DiamondFacetsHelper.sol"; @@ -255,7 +255,8 @@ contract SubnetRegistryTest is Test, TestRegistry, IntegrationTestBase { activeValidatorsLimit: _activeValidatorsLimit, powerScale: _powerScale, permissionMode: PermissionMode.Collateral, - supplySource: SupplySourceHelper.native(), + supplySource: AssetHelper.native(), + collateralSource: AssetHelper.native(), validatorGater: address(0) }); diff --git a/contracts/test/invariants/SubnetActorInvariants.t.sol b/contracts/test/invariants/SubnetActorInvariants.t.sol index 3176d0b331..1dc251301c 100644 --- a/contracts/test/invariants/SubnetActorInvariants.t.sol +++ b/contracts/test/invariants/SubnetActorInvariants.t.sol @@ -15,7 +15,7 @@ import {SubnetActorHandler, ETH_SUPPLY} from "./handlers/SubnetActorHandler.sol" import {SubnetActorMock} from "../mocks/SubnetActorMock.sol"; import {SubnetActorGetterFacet} from "../../contracts/subnet/SubnetActorGetterFacet.sol"; import {IntegrationTestBase} from "../IntegrationTestBase.sol"; -import {SupplySourceHelper} from "../../contracts/lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../../contracts/lib/AssetHelper.sol"; import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; import {SubnetActorFacetsHelper} from "../helpers/SubnetActorFacetsHelper.sol"; import {GatewayFacetsHelper} from "../helpers/GatewayFacetsHelper.sol"; diff --git a/contracts/test/invariants/handlers/GatewayActorHandler.sol b/contracts/test/invariants/handlers/GatewayActorHandler.sol index 9ba944c0f5..47651e55a8 100644 --- a/contracts/test/invariants/handlers/GatewayActorHandler.sol +++ b/contracts/test/invariants/handlers/GatewayActorHandler.sol @@ -24,12 +24,12 @@ contract GatewayActorHandler is CommonBase, StdCheats, StdUtils { function register(uint256 amount) public { amount = bound(amount, 0, 3 * DEFAULT_MIN_VALIDATOR_STAKE); - managerFacet.register(amount); + managerFacet.register(amount, 0); } function stake(uint256 amount) public { amount = bound(amount, 0, 3 * DEFAULT_MIN_VALIDATOR_STAKE); - managerFacet.addStake{value: amount}(); + managerFacet.addStake{value: amount}(amount); } function _pay(address to, uint256 amount) internal { diff --git a/contracts/test/invariants/handlers/SubnetActorHandler.sol b/contracts/test/invariants/handlers/SubnetActorHandler.sol index 9b5d014fa5..efbd957eee 100644 --- a/contracts/test/invariants/handlers/SubnetActorHandler.sol +++ b/contracts/test/invariants/handlers/SubnetActorHandler.sol @@ -80,7 +80,7 @@ contract SubnetActorHandler is CommonBase, StdCheats, StdUtils { _pay(validator, amount); vm.prank(validator); - managerFacet.join{value: amount}(publicKey); + managerFacet.join{value: amount}(publicKey, amount); managerFacet.confirmNextChange(); ghost_stakedSum += amount; @@ -94,7 +94,7 @@ contract SubnetActorHandler is CommonBase, StdCheats, StdUtils { _pay(validator, amount); vm.prank(validator); - managerFacet.stake{value: amount}(); + managerFacet.stake{value: amount}(amount); managerFacet.confirmNextChange(); ghost_stakedSum += amount; diff --git a/contracts/test/invariants/handlers/SubnetRegistryHandler.sol b/contracts/test/invariants/handlers/SubnetRegistryHandler.sol index 4b5ec3060b..6883831979 100644 --- a/contracts/test/invariants/handlers/SubnetRegistryHandler.sol +++ b/contracts/test/invariants/handlers/SubnetRegistryHandler.sol @@ -10,7 +10,7 @@ import {SubnetActorDiamond} from "../../../contracts/SubnetActorDiamond.sol"; import {SubnetRegistryDiamond} from "../../../contracts/SubnetRegistryDiamond.sol"; import {ConsensusType} from "../../../contracts/enums/ConsensusType.sol"; import {SubnetID, PermissionMode} from "../../../contracts/structs/Subnet.sol"; -import {SupplySourceHelper} from "../../../contracts/lib/SupplySourceHelper.sol"; +import {AssetHelper} from "../../../contracts/lib/AssetHelper.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {RegistryFacetsHelper} from "../../helpers/RegistryFacetsHelper.sol"; @@ -122,7 +122,8 @@ contract SubnetRegistryHandler is CommonBase, StdCheats, StdUtils { activeValidatorsLimit: _activeValidatorsLimit, powerScale: _powerScale, permissionMode: PermissionMode.Collateral, - supplySource: SupplySourceHelper.native(), + supplySource: AssetHelper.native(), + collateralSource: AssetHelper.native(), validatorGater: address(0) }); diff --git a/contracts/test/mocks/AssetHelperMock.sol b/contracts/test/mocks/AssetHelperMock.sol new file mode 100644 index 0000000000..702a3adc3b --- /dev/null +++ b/contracts/test/mocks/AssetHelperMock.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.23; + +import {Asset} from "../../contracts/structs/Subnet.sol"; +import {AssetHelper} from "../../contracts/lib/AssetHelper.sol"; + +/// @notice Helpers to deal with a supply source. +contract AssetHelperMock { + function performCall( + Asset memory supplySource, + address payable target, + bytes memory data, + uint256 value + ) public returns (bool success, bytes memory ret) { + return AssetHelper.performCall(supplySource, target, data, value); + } +} diff --git a/contracts/test/mocks/SupplySourceHelperMock.sol b/contracts/test/mocks/SupplySourceHelperMock.sol deleted file mode 100644 index fa7f50e511..0000000000 --- a/contracts/test/mocks/SupplySourceHelperMock.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.23; - -import {SupplySource} from "../../contracts/structs/Subnet.sol"; -import {SupplySourceHelper} from "../../contracts/lib/SupplySourceHelper.sol"; - -/// @notice Helpers to deal with a supply source. -contract SupplySourceHelperMock { - function performCall( - SupplySource memory supplySource, - address payable target, - bytes memory data, - uint256 value - ) public returns (bool success, bytes memory ret) { - return SupplySourceHelper.performCall(supplySource, target, data, value); - } -} diff --git a/contracts/test/unit/CrossMsgHelper.t.sol b/contracts/test/unit/CrossMsgHelper.t.sol index 486a11591f..e71d0e154b 100644 --- a/contracts/test/unit/CrossMsgHelper.t.sol +++ b/contracts/test/unit/CrossMsgHelper.t.sol @@ -6,7 +6,7 @@ import "../../contracts/lib/CrossMsgHelper.sol"; import "../../contracts/lib/SubnetIDHelper.sol"; import "../../contracts/lib/FvmAddressHelper.sol"; import {FvmAddress} from "../../contracts/structs/FvmAddress.sol"; -import {SupplySource} from "../../contracts/structs/Subnet.sol"; +import {Asset} from "../../contracts/structs/Subnet.sol"; import {IpcMsgKind, CallMsg} from "../../contracts/structs/CrossNet.sol"; import "@openzeppelin/contracts/utils/Address.sol"; @@ -156,7 +156,7 @@ contract CrossMsgHelperTest is Test { vm.deal(sender, 1 ether); - (, bytes memory result) = crossMsg.execute(SupplySourceHelper.native()); + (, bytes memory result) = crossMsg.execute(AssetHelper.native()); require(keccak256(result) == keccak256(EMPTY_BYTES)); require(recipient.balance == 1); @@ -178,7 +178,7 @@ contract CrossMsgHelperTest is Test { vm.deal(sender, 1 ether); vm.expectCall(recipient, crossMsg.value, new bytes(0), 1); - (, bytes memory result) = crossMsg.execute(SupplySourceHelper.native()); + (, bytes memory result) = crossMsg.execute(AssetHelper.native()); require(keccak256(result) == keccak256(EMPTY_BYTES)); } @@ -198,13 +198,13 @@ contract CrossMsgHelperTest is Test { vm.deal(sender, 1 ether); vm.expectCall(recipient, crossMsg.value, new bytes(0), 1); - (, bytes memory result) = crossMsg.execute(SupplySourceHelper.native()); + (, bytes memory result) = crossMsg.execute(AssetHelper.native()); require(keccak256(result) == keccak256(EMPTY_BYTES)); } function test_Execute_Fails_InvalidMethod() public { - SupplySource memory native = SupplySourceHelper.native(); + Asset memory native = AssetHelper.native(); crossMsg.kind = IpcMsgKind.Call; crossMsg.to.rawAddress = FvmAddressHelper.from(address(this)); diff --git a/contracts/test/unit/SupplySourceHelper.t.sol b/contracts/test/unit/GenericTokenHelper.t.sol similarity index 68% rename from contracts/test/unit/SupplySourceHelper.t.sol rename to contracts/test/unit/GenericTokenHelper.t.sol index 2410dc5c90..1ba246c9e5 100644 --- a/contracts/test/unit/SupplySourceHelper.t.sol +++ b/contracts/test/unit/GenericTokenHelper.t.sol @@ -5,10 +5,10 @@ import "forge-std/Test.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "../../contracts/lib/SubnetIDHelper.sol"; -import {SupplySource, SupplyKind} from "../../contracts/structs/Subnet.sol"; -import {SupplySourceHelper} from "../../contracts/lib/SupplySourceHelper.sol"; +import {Asset, AssetKind} from "../../contracts/structs/Subnet.sol"; +import {AssetHelper} from "../../contracts/lib/AssetHelper.sol"; -import {SupplySourceHelperMock} from "../mocks/SupplySourceHelperMock.sol"; +import {AssetHelperMock} from "../mocks/AssetHelperMock.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -22,15 +22,15 @@ contract FailingContract { } } -contract SupplySourceHelperTest is Test { +contract AssetHelperTest is Test { /// Call fails but send value works, both should fail function test_revert_atomicity_no_ret() public { uint256 balance = 1_000_000; - SupplySourceHelperMock mock = new SupplySourceHelperMock(); + AssetHelperMock mock = new AssetHelperMock(); IERC20 token = new ERC20PresetFixedSupply("TestToken", "TEST", balance, address(mock)); - SupplySource memory source = SupplySource({kind: SupplyKind.ERC20, tokenAddress: address(token)}); + Asset memory source = Asset({kind: AssetKind.ERC20, tokenAddress: address(token)}); bytes memory params = bytes("hello"); @@ -42,11 +42,11 @@ contract SupplySourceHelperTest is Test { function test_revert_atomicity_with_ret() public { uint256 balance = 1_000_000; - SupplySourceHelperMock mock = new SupplySourceHelperMock(); + AssetHelperMock mock = new AssetHelperMock(); IERC20 token = new ERC20PresetFixedSupply("TestToken", "TEST", balance, address(mock)); - SupplySource memory source = SupplySource({kind: SupplyKind.ERC20, tokenAddress: address(token)}); + Asset memory source = Asset({kind: AssetKind.ERC20, tokenAddress: address(token)}); bytes memory params = abi.encodeWithSelector(FailingContract.failing.selector); @@ -60,11 +60,11 @@ contract SupplySourceHelperTest is Test { function test_call_with_erc20_ok() public { uint256 balance = 1_000_000; uint256 value = 100; - SupplySourceHelperMock mock = new SupplySourceHelperMock(); + AssetHelperMock mock = new AssetHelperMock(); IERC20 token = new ERC20PresetFixedSupply("TestToken", "TEST", balance, address(mock)); - SupplySource memory source = SupplySource({kind: SupplyKind.ERC20, tokenAddress: address(token)}); + Asset memory source = Asset({kind: AssetKind.ERC20, tokenAddress: address(token)}); bytes memory params = bytes("hello"); @@ -76,9 +76,9 @@ contract SupplySourceHelperTest is Test { function test_call_with_native_zero_balance_ok() public { uint256 value = 0; - SupplySourceHelperMock mock = new SupplySourceHelperMock(); + AssetHelperMock mock = new AssetHelperMock(); - SupplySource memory source = SupplySource({kind: SupplyKind.Native, tokenAddress: address(0)}); + Asset memory source = Asset({kind: AssetKind.Native, tokenAddress: address(0)}); bytes memory params = bytes("hello"); @@ -88,11 +88,11 @@ contract SupplySourceHelperTest is Test { function test_call_with_native_ok() public { uint256 value = 10; - SupplySourceHelperMock mock = new SupplySourceHelperMock(); + AssetHelperMock mock = new AssetHelperMock(); vm.deal(address(mock), 1 ether); - SupplySource memory source = SupplySource({kind: SupplyKind.Native, tokenAddress: address(0)}); + Asset memory source = Asset({kind: AssetKind.Native, tokenAddress: address(0)}); bytes memory params = bytes("hello"); @@ -102,11 +102,11 @@ contract SupplySourceHelperTest is Test { function test_call_with_native_reverts() public { uint256 value = 10; - SupplySourceHelperMock mock = new SupplySourceHelperMock(); + AssetHelperMock mock = new AssetHelperMock(); vm.deal(address(mock), 1 ether); - SupplySource memory source = SupplySource({kind: SupplyKind.Native, tokenAddress: address(0)}); + Asset memory source = Asset({kind: AssetKind.Native, tokenAddress: address(0)}); bytes memory params = bytes("hello"); diff --git a/extras/axelar-token/contracts/IpcTokenHandler.sol b/extras/axelar-token/contracts/IpcTokenHandler.sol index fe03337e5d..750aefc9f3 100644 --- a/extras/axelar-token/contracts/IpcTokenHandler.sol +++ b/extras/axelar-token/contracts/IpcTokenHandler.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import { InterchainTokenExecutable } from '@axelar-network/interchain-token-service/contracts/executable/InterchainTokenExecutable.sol'; import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { SubnetID, SupplySource, SupplyKind } from "@consensus-shipyard/ipc-contracts/contracts/structs/Subnet.sol"; +import { SubnetID, Asset, AssetKind } from "@consensus-shipyard/ipc-contracts/contracts/structs/Subnet.sol"; import { FvmAddress } from "@consensus-shipyard/ipc-contracts/contracts/structs/FvmAddress.sol"; import { IIpcHandler } from "@consensus-shipyard/ipc-contracts/sdk/interfaces/IIpcHandler.sol"; import { IpcMsgKind, ResultMsg, OutcomeType, IpcEnvelope } from "@consensus-shipyard/ipc-contracts/contracts/structs/CrossNet.sol"; @@ -17,7 +17,7 @@ interface TokenFundedGateway { } interface SubnetActor { - function supplySource() external returns (SupplySource memory supply); + function supplySource() external returns (Asset memory supply); } // @notice The IpcTokenHandler sits in an Axelar-supported L1 housing an IPC subnet hierarchy. It is invoked by the @@ -93,8 +93,8 @@ contract IpcTokenHandler is InterchainTokenExecutable, IIpcHandler, Ownable { ResultMsg memory result = abi.decode(envelope.message, (ResultMsg)); if (result.outcome != OutcomeType.Ok) { // Verify that the subnet is indeed an ERC20 subnet. - SupplySource memory supplySource = SubnetActor(envelope.from.subnetId.getAddress()).supplySource(); - require(supplySource.kind == SupplyKind.ERC20, "expected ERC20 supply source"); + Asset memory supplySource = SubnetActor(envelope.from.subnetId.getAddress()).supplySource(); + require(supplySource.kind == AssetKind.ERC20, "expected ERC20 supply source"); // Increase the allowance of the admin address so they can retrieve these otherwise lost tokens. IERC20(supplySource.tokenAddress).safeIncreaseAllowance(owner(), envelope.value); diff --git a/extras/linked-token/test/MultiSubnetTest.t.sol b/extras/linked-token/test/MultiSubnetTest.t.sol index b2744880b0..38143279f9 100644 --- a/extras/linked-token/test/MultiSubnetTest.t.sol +++ b/extras/linked-token/test/MultiSubnetTest.t.sol @@ -404,7 +404,7 @@ contract MultiSubnetTest is IntegrationTestBase { vm.deal(parentValidators[i], 10 gwei); parentPubKeys[i] = TestUtils.deriveValidatorPubKeyBytes(parentKeys[i]); vm.prank(parentValidators[i]); - manager.join{value: 10}(parentPubKeys[i]); + manager.join{value: 10}(parentPubKeys[i], 10); } bytes32 hash = keccak256(abi.encode(checkpoint)); diff --git a/fendermint/testing/contract-test/src/ipc/subnet.rs b/fendermint/testing/contract-test/src/ipc/subnet.rs index 6f74be7b30..1b7c9e905c 100644 --- a/fendermint/testing/contract-test/src/ipc/subnet.rs +++ b/fendermint/testing/contract-test/src/ipc/subnet.rs @@ -62,7 +62,7 @@ impl SubnetCaller { // We need to send in the name of the address as a sender, not the system account. self.manager.call(state, |c| { - c.join(public_key.into()).from(addr).value(deposit) + c.join(public_key.into(), deposit).from(addr).value(deposit) }) } @@ -76,7 +76,7 @@ impl SubnetCaller { let addr = EthAddress::new_secp256k1(&public_key)?; let deposit = from_fvm::to_eth_tokens(&validator.power.0)?; self.manager.try_call(state, |c| { - c.join(public_key.into()).from(addr).value(deposit) + c.join(public_key.into(), deposit).from(addr).value(deposit) }) } @@ -89,7 +89,7 @@ impl SubnetCaller { ) -> TryCallResult<()> { let deposit = from_fvm::to_eth_tokens(value)?; self.manager - .try_call(state, |c| c.stake().from(addr).value(deposit)) + .try_call(state, |c| c.stake(deposit).from(addr).value(deposit)) } /// Try to decrease the stake of a validator. diff --git a/fendermint/testing/contract-test/tests/staking/machine.rs b/fendermint/testing/contract-test/tests/staking/machine.rs index 174475ef83..7aed62ea5e 100644 --- a/fendermint/testing/contract-test/tests/staking/machine.rs +++ b/fendermint/testing/contract-test/tests/staking/machine.rs @@ -111,7 +111,11 @@ impl StateMachine for StakingMachine { min_activation_collateral: to_eth_tokens(&state.min_collateral()).unwrap(), min_validators: state.min_validators() as u64, permission_mode: 0, // collateral based - supply_source: ipc_actors_abis::register_subnet_facet::SupplySource { + supply_source: ipc_actors_abis::register_subnet_facet::Asset { + kind: 0, // native token + token_address: ethers::types::Address::zero(), + }, + collateral_source: ipc_actors_abis::register_subnet_facet::Asset { kind: 0, // native token token_address: ethers::types::Address::zero(), }, diff --git a/ipc/api/src/evm.rs b/ipc/api/src/evm.rs index 79c6a84cf6..4c842fea66 100644 --- a/ipc/api/src/evm.rs +++ b/ipc/api/src/evm.rs @@ -9,7 +9,7 @@ use crate::checkpoint::BottomUpMsgBatch; use crate::cross::{IpcEnvelope, IpcMsgKind}; use crate::staking::StakingChange; use crate::staking::StakingChangeRequest; -use crate::subnet::SupplySource; +use crate::subnet::{Asset, AssetKind}; use crate::subnet_id::SubnetID; use crate::{eth_to_fil_amount, ethers_address_to_fil_address}; use anyhow::anyhow; @@ -180,6 +180,45 @@ macro_rules! bottom_up_msg_batch_conversion { }; } +/// The type conversion between different asset token types +macro_rules! asset_conversion { + ($module:ident) => { + impl TryFrom for $module::Asset { + type Error = anyhow::Error; + + fn try_from(value: Asset) -> Result { + let token_address = if let Some(token_address) = value.token_address { + payload_to_evm_address(token_address.payload())? + } else { + ethers::types::Address::zero() + }; + + Ok(Self { + kind: value.kind as u8, + token_address, + }) + } + } + + impl TryFrom<$module::Asset> for Asset { + type Error = anyhow::Error; + + fn try_from(value: $module::Asset) -> Result { + let token_address = if value.token_address == ethers::types::Address::zero() { + None + } else { + Some(ethers_address_to_fil_address(&value.token_address)?) + }; + + Ok(Self { + kind: AssetKind::try_from(value.kind)?, + token_address, + }) + } + } + }; +} + base_type_conversion!(xnet_messaging_facet); base_type_conversion!(subnet_actor_getter_facet); base_type_conversion!(gateway_manager_facet); @@ -198,37 +237,19 @@ bottom_up_checkpoint_conversion!(gateway_getter_facet); bottom_up_checkpoint_conversion!(subnet_actor_checkpointing_facet); bottom_up_msg_batch_conversion!(gateway_getter_facet); -impl TryFrom for subnet_actor_diamond::SupplySource { - type Error = anyhow::Error; - - fn try_from(value: SupplySource) -> Result { - let token_address = if let Some(token_address) = value.token_address { - payload_to_evm_address(token_address.payload())? - } else { - ethers::types::Address::zero() - }; +asset_conversion!(subnet_actor_diamond); +asset_conversion!(register_subnet_facet); +asset_conversion!(subnet_actor_getter_facet); - Ok(Self { - kind: value.kind as u8, - token_address, - }) - } -} - -impl TryFrom for register_subnet_facet::SupplySource { +impl TryFrom for AssetKind { type Error = anyhow::Error; - fn try_from(value: SupplySource) -> Result { - let token_address = if let Some(token_address) = value.token_address { - payload_to_evm_address(token_address.payload())? - } else { - ethers::types::Address::zero() - }; - - Ok(Self { - kind: value.kind as u8, - token_address, - }) + fn try_from(value: u8) -> Result { + match value { + 0 => Ok(AssetKind::Native), + 1 => Ok(AssetKind::ERC20), + _ => Err(anyhow!("invalid kind {value}")), + } } } diff --git a/ipc/api/src/subnet.rs b/ipc/api/src/subnet.rs index 16883b1fbe..386df79a3e 100644 --- a/ipc/api/src/subnet.rs +++ b/ipc/api/src/subnet.rs @@ -37,16 +37,25 @@ pub enum PermissionMode { Static, } -/// Defines the supply source of a subnet on its parent subnet. +/// Defines a generic token of a subnet on its parent subnet. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct SupplySource { +pub struct Asset { /// The kind of supply. - pub kind: SupplyKind, + pub kind: AssetKind, /// The address of the ERC20 token if that supply kind is selected. pub token_address: Option
, } -/// Determines the type of supply used by the subnet. +impl Default for Asset { + fn default() -> Self { + Self { + kind: AssetKind::Native, + token_address: None, + } + } +} + +/// Determines the type of a token used by the subnet. #[repr(u8)] #[derive( Copy, @@ -60,7 +69,7 @@ pub struct SupplySource { strum::VariantNames, )] #[strum(serialize_all = "snake_case")] -pub enum SupplyKind { +pub enum AssetKind { Native, ERC20, } @@ -76,7 +85,8 @@ pub struct ConstructParams { pub active_validators_limit: u16, pub min_cross_msg_fee: TokenAmount, pub permission_mode: PermissionMode, - pub supply_source: SupplySource, + pub supply_source: Asset, + pub collateral_source: Asset, pub validator_gater: Address, } diff --git a/ipc/cli/src/commands/subnet/create.rs b/ipc/cli/src/commands/subnet/create.rs index fdc1d6e846..f170827f0a 100644 --- a/ipc/cli/src/commands/subnet/create.rs +++ b/ipc/cli/src/commands/subnet/create.rs @@ -9,7 +9,7 @@ use async_trait::async_trait; use clap::Args; use fvm_shared::clock::ChainEpoch; -use ipc_api::subnet::{PermissionMode, SupplyKind, SupplySource}; +use ipc_api::subnet::{Asset, AssetKind, PermissionMode}; use ipc_api::subnet_id::SubnetID; use crate::commands::get_ipc_provider; @@ -34,15 +34,8 @@ impl CreateSubnet { None => None, }; - let token_address = if let Some(addr) = &arguments.supply_source_address { - Some(require_fil_addr_from_str(addr)?) - } else { - None - }; - let supply_source = SupplySource { - kind: arguments.supply_source_kind, - token_address, - }; + let supply_source = parse_supply_source(arguments)?; + let collateral_source = parse_collateral_source(arguments)?; let raw_addr = arguments .validator_gater @@ -62,6 +55,7 @@ impl CreateSubnet { f64_to_token_amount(arguments.min_cross_msg_fee)?, arguments.permission_mode, supply_source, + collateral_source, validator_gater, ) .await?; @@ -70,6 +64,35 @@ impl CreateSubnet { } } +fn parse_supply_source(arguments: &CreateSubnetArgs) -> anyhow::Result { + let token_address = if let Some(addr) = &arguments.supply_source_address { + Some(require_fil_addr_from_str(addr)?) + } else { + None + }; + Ok(Asset { + kind: arguments.supply_source_kind, + token_address, + }) +} + +fn parse_collateral_source(arguments: &CreateSubnetArgs) -> anyhow::Result { + let Some(ref kind) = arguments.collateral_source_kind else { + return Ok(Asset::default()); + }; + + let token_address = if let Some(addr) = &arguments.collateral_source_address { + Some(require_fil_addr_from_str(addr)?) + } else { + None + }; + + Ok(Asset { + kind: *kind, + token_address, + }) +} + #[async_trait] impl CommandLineHandler for CreateSubnet { type Arguments = CreateSubnetArgs; @@ -127,11 +150,11 @@ pub struct CreateSubnetArgs { #[arg( long, help = "The kind of supply source of a subnet on its parent subnet: native or erc20", - value_parser = SupplyKind::from_str, + value_parser = AssetKind::from_str, )] - // TODO figure out a way to use a newtype + ValueEnum, or reference SupplySourceKind::VARIANTS to + // TODO figure out a way to use a newtype + ValueEnum, or reference AssetKind::VARIANTS to // enumerate all variants - pub supply_source_kind: SupplyKind, + pub supply_source_kind: AssetKind, #[arg( long, help = "The address of supply source of a subnet on its parent subnet. None if kind is native" @@ -142,4 +165,15 @@ pub struct CreateSubnetArgs { help = "The address of validator gating contract. None if validator gating is disabled" )] pub validator_gater: Option, + #[arg( + long, + help = "The kind of collateral source of a subnet on its parent subnet: native or erc20", + value_parser = AssetKind::from_str, + )] + pub collateral_source_kind: Option, + #[arg( + long, + help = "The address of collateral source of a subnet on its parent subnet. None if kind is native" + )] + pub collateral_source_address: Option, } diff --git a/ipc/provider/src/lib.rs b/ipc/provider/src/lib.rs index 10118012a3..5fa469f309 100644 --- a/ipc/provider/src/lib.rs +++ b/ipc/provider/src/lib.rs @@ -12,7 +12,7 @@ use fvm_shared::{ use ipc_api::checkpoint::{BottomUpCheckpointBundle, QuorumReachedEvent}; use ipc_api::evm::payload_to_evm_address; use ipc_api::staking::{StakingChangeRequest, ValidatorInfo}; -use ipc_api::subnet::{PermissionMode, SupplySource}; +use ipc_api::subnet::{Asset, PermissionMode}; use ipc_api::{ cross::IpcEnvelope, subnet::{ConsensusType, ConstructParams}, @@ -253,7 +253,8 @@ impl IpcProvider { active_validators_limit: u16, min_cross_msg_fee: TokenAmount, permission_mode: PermissionMode, - supply_source: SupplySource, + supply_source: Asset, + collateral_source: Asset, validator_gater: Address, ) -> anyhow::Result
{ let conn = self.get_connection(&parent)?; @@ -272,6 +273,7 @@ impl IpcProvider { min_cross_msg_fee, permission_mode, supply_source, + collateral_source, validator_gater, }; diff --git a/ipc/provider/src/manager/evm/manager.rs b/ipc/provider/src/manager/evm/manager.rs index c8007ee954..21fc3416fe 100644 --- a/ipc/provider/src/manager/evm/manager.rs +++ b/ipc/provider/src/manager/evm/manager.rs @@ -19,7 +19,7 @@ use reqwest::header::HeaderValue; use reqwest::Client; use std::net::{IpAddr, SocketAddr}; -use ipc_api::subnet::{PermissionMode, SupplyKind, SupplySource}; +use ipc_api::subnet::{Asset, AssetKind, PermissionMode}; use ipc_api::{eth_to_fil_amount, ethers_address_to_fil_address}; use crate::config::subnet::SubnetConfig; @@ -275,7 +275,8 @@ impl SubnetManager for EthSubnetManager { active_validators_limit: params.active_validators_limit, power_scale: 3, permission_mode: params.permission_mode as u8, - supply_source: register_subnet_facet::SupplySource::try_from(params.supply_source)?, + supply_source: register_subnet_facet::Asset::try_from(params.supply_source)?, + collateral_source: register_subnet_facet::Asset::try_from(params.collateral_source)?, validator_gater: payload_to_evm_address(params.validator_gater.payload())?, }; @@ -344,8 +345,9 @@ impl SubnetManager for EthSubnetManager { let contract = subnet_actor_manager_facet::SubnetActorManagerFacet::new(address, signer.clone()); - let mut txn = contract.join(ethers::types::Bytes::from(pub_key)); - txn.tx.set_value(collateral); + let mut txn = contract.join(ethers::types::Bytes::from(pub_key), U256::from(collateral)); + txn = self.handle_txn_token(&subnet, txn, collateral, 0).await?; + let txn = call_with_premium_estimation(signer, txn).await?; // Use the pending state to get the nonce because there could have been a pre-fund. Best would be to use this for everything. @@ -369,8 +371,9 @@ impl SubnetManager for EthSubnetManager { let contract = subnet_actor_manager_facet::SubnetActorManagerFacet::new(address, signer.clone()); - let mut txn = contract.pre_fund(); - txn.tx.set_value(balance); + let mut txn = contract.pre_fund(U256::from(balance)); + txn = self.handle_txn_token(&subnet, txn, 0, balance).await?; + let txn = call_with_premium_estimation(signer, txn).await?; txn.send().await?; @@ -419,8 +422,9 @@ impl SubnetManager for EthSubnetManager { let contract = subnet_actor_manager_facet::SubnetActorManagerFacet::new(address, signer.clone()); - let mut txn = contract.stake(); - txn.tx.set_value(collateral); + let mut txn = contract.stake(U256::from(collateral)); + txn = self.handle_txn_token(&subnet, txn, collateral, 0).await?; + let txn = call_with_premium_estimation(signer, txn).await?; txn.send().await?.await?; @@ -581,11 +585,17 @@ impl SubnetManager for EthSubnetManager { let signer = Arc::new(self.get_signer(&from)?); let subnet_supply_source = self.get_subnet_supply_source(&subnet).await?; - if subnet_supply_source.kind != SupplyKind::ERC20 as u8 { + if subnet_supply_source.kind != AssetKind::ERC20 { return Err(anyhow!("Invalid operation: Expected the subnet's supply source to be ERC20, but found a different kind.")); } - let token_contract = IERC20::new(subnet_supply_source.token_address, signer.clone()); + let token_address = payload_to_evm_address( + subnet_supply_source + .token_address + .ok_or_else(|| anyhow!("zero adress not erc20"))? + .payload(), + )?; + let token_contract = IERC20::new(token_address, signer.clone()); let txn = token_contract.approve(self.ipc_contract_info.gateway_addr, value); let txn = call_with_premium_estimation(signer, txn).await?; @@ -755,16 +765,24 @@ impl SubnetManager for EthSubnetManager { Ok(commit_sha) } - async fn get_subnet_supply_source( - &self, - subnet: &SubnetID, - ) -> Result { + async fn get_subnet_supply_source(&self, subnet: &SubnetID) -> Result { + let address = contract_address_from_subnet(subnet)?; + let contract = subnet_actor_getter_facet::SubnetActorGetterFacet::new( + address, + Arc::new(self.ipc_contract_info.provider.clone()), + ); + let raw = contract.collateral_source().call().await?; + Ok(Asset::try_from(raw)?) + } + + async fn get_subnet_collateral_source(&self, subnet: &SubnetID) -> Result { let address = contract_address_from_subnet(subnet)?; let contract = subnet_actor_getter_facet::SubnetActorGetterFacet::new( address, Arc::new(self.ipc_contract_info.provider.clone()), ); - Ok(contract.supply_source().call().await?) + let raw = contract.collateral_source().call().await?; + Ok(Asset::try_from(raw)?) } async fn get_genesis_info(&self, subnet: &SubnetID) -> Result { @@ -793,8 +811,8 @@ impl SubnetManager for EthSubnetManager { genesis_balances: into_genesis_balance_map(genesis_balances.0, genesis_balances.1)?, // TODO: fixme https://github.com/consensus-shipyard/ipc-monorepo/issues/496 permission_mode: PermissionMode::Collateral, - supply_source: SupplySource { - kind: SupplyKind::Native, + supply_source: Asset { + kind: AssetKind::Native, token_address: None, }, }) @@ -1020,6 +1038,31 @@ impl EthSubnetManager { } } + /// This method handles the "msg.value" based on different collateral/supply source + /// asset kind. + pub async fn handle_txn_token( + &self, + subnet: &SubnetID, + mut txn: ethers_contract::FunctionCall, + collateral: u128, + balance: u128, + ) -> anyhow::Result> + where + B: std::borrow::Borrow, + M: ethers::abi::Detokenize, + { + let supply_source = self.get_subnet_supply_source(subnet).await?; + let collateral_source = self.get_subnet_collateral_source(subnet).await?; + + match (supply_source.kind, collateral_source.kind) { + (AssetKind::Native, AssetKind::Native) => _ = txn.tx.set_value(balance + collateral), + (AssetKind::Native, AssetKind::ERC20) => _ = txn.tx.set_value(balance), + (AssetKind::ERC20, AssetKind::Native) => _ = txn.tx.set_value(collateral), + _ => {} + } + Ok(txn) + } + pub fn ensure_same_gateway(&self, gateway: &Address) -> Result<()> { let evm_gateway_addr = payload_to_evm_address(gateway.payload())?; if evm_gateway_addr != self.ipc_contract_info.gateway_addr { diff --git a/ipc/provider/src/manager/subnet.rs b/ipc/provider/src/manager/subnet.rs index b908b9b3ff..cc47ab093a 100644 --- a/ipc/provider/src/manager/subnet.rs +++ b/ipc/provider/src/manager/subnet.rs @@ -12,7 +12,7 @@ use ipc_api::checkpoint::{ }; use ipc_api::cross::IpcEnvelope; use ipc_api::staking::{StakingChangeRequest, ValidatorInfo}; -use ipc_api::subnet::{ConstructParams, PermissionMode, SupplySource}; +use ipc_api::subnet::{Asset, ConstructParams, PermissionMode}; use ipc_api::subnet_id::SubnetID; use ipc_api::validator::Validator; @@ -163,10 +163,10 @@ pub trait SubnetManager: Send + Sync + TopDownFinalityQuery + BottomUpCheckpoint async fn get_commit_sha(&self) -> Result<[u8; 32]>; /// Gets the subnet supply source - async fn get_subnet_supply_source( - &self, - subnet: &SubnetID, - ) -> Result; + async fn get_subnet_supply_source(&self, subnet: &SubnetID) -> Result; + + /// Gets the subnet collateral source + async fn get_subnet_collateral_source(&self, subnet: &SubnetID) -> Result; /// Gets the genesis information required to bootstrap a child subnet async fn get_genesis_info(&self, subnet: &SubnetID) -> Result; @@ -209,7 +209,7 @@ pub struct SubnetGenesisInfo { pub validators: Vec, pub genesis_balances: BTreeMap, pub permission_mode: PermissionMode, - pub supply_source: SupplySource, + pub supply_source: Asset, } /// The generic payload that returns the block hash of the data returning block with the actual diff --git a/ipc/wallet/src/fvm/keystore.rs b/ipc/wallet/src/fvm/keystore.rs index 024d49bbe5..b3a033f4e8 100644 --- a/ipc/wallet/src/fvm/keystore.rs +++ b/ipc/wallet/src/fvm/keystore.rs @@ -191,11 +191,11 @@ impl KeyStore { // Existing cleartext JSON keystore let persisted_key_info: HashMap = serde_json::from_reader(reader) - .inspect_err(|_e| { + .inspect_err(|_| { error!( - "failed to deserialize keyfile, initializing new keystore at: {:?}", - file_path - ); + "failed to deserialize keyfile, initializing new keystore at: {:?}", + file_path + ); }) .unwrap_or_default(); @@ -291,8 +291,8 @@ impl KeyStore { .map_err(|error| Error::Other(error.to_string()))?; let key_info = serde_ipld_dagcbor::from_slice(&decrypted_data) - .inspect_err(|_e| { - error!("failed to deserialize keyfile, initializing new"); + .inspect_err(|_| { + error!("Failed to deserialize keyfile, initializing new"); }) .unwrap_or_default();